/[dynamips]/trunk/dynamips.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 /trunk/dynamips.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 9 - (hide annotations)
Sat Oct 6 16:26:06 2007 UTC (16 years, 5 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.7-RC3/dynamips.c
File MIME type: text/plain
File size: 37225 byte(s)
dynamips-0.2.7-RC3

1 dpavlin 1 /*
2 dpavlin 7 * Cisco router simulation platform.
3 dpavlin 1 * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)
4     *
5     * Many thanks to Nicolas Szalay for his patch
6     * for the command line parsing and virtual machine
7     * settings (RAM, ROM, NVRAM, ...)
8     */
9    
10     #include <stdio.h>
11     #include <stdlib.h>
12     #include <unistd.h>
13     #include <string.h>
14     #include <errno.h>
15     #include <sys/types.h>
16     #include <sys/stat.h>
17     #include <sys/mman.h>
18     #include <signal.h>
19     #include <fcntl.h>
20     #include <assert.h>
21     #include <getopt.h>
22    
23     #include "dynamips.h"
24 dpavlin 7 #include "cpu.h"
25 dpavlin 1 #include "mips64_exec.h"
26 dpavlin 7 #include "mips64_jit.h"
27     #include "ppc32_exec.h"
28     #include "ppc32_jit.h"
29 dpavlin 1 #include "dev_c7200.h"
30     #include "dev_c3600.h"
31 dpavlin 4 #include "dev_c2691.h"
32     #include "dev_c3725.h"
33     #include "dev_c3745.h"
34 dpavlin 7 #include "dev_c2600.h"
35 dpavlin 8 #include "dev_msfc1.h"
36 dpavlin 7 #include "ppc32_vmtest.h"
37 dpavlin 1 #include "dev_vtty.h"
38     #include "ptask.h"
39 dpavlin 3 #include "timer.h"
40 dpavlin 1 #include "registry.h"
41     #include "hypervisor.h"
42     #include "net_io.h"
43     #include "net_io_bridge.h"
44     #include "net_io_filter.h"
45     #include "crc.h"
46     #include "atm.h"
47     #include "frame_relay.h"
48     #include "eth_switch.h"
49     #ifdef GEN_ETH
50     #include "gen_eth.h"
51     #endif
52     #ifdef PROFILE
53     #include "profiler.h"
54     #endif
55    
56     /* Default name for logfile */
57     #define LOGFILE_DEFAULT_NAME "dynamips_log.txt"
58    
59     /* Software version */
60     const char *sw_version = DYNAMIPS_VERSION"-"JIT_ARCH;
61    
62 dpavlin 8 /* Software version tag */
63 dpavlin 9 const char *sw_version_tag = "2007042500";
64 dpavlin 8
65 dpavlin 1 /* Hypervisor */
66     int hypervisor_mode = 0;
67     int hypervisor_tcp_port = 0;
68    
69     /* Log file */
70     char *log_file_name = NULL;
71     FILE *log_file = NULL;
72    
73     /* VM flags */
74     volatile int vm_save_state = 0;
75    
76     /* Generic signal handler */
77     void signal_gen_handler(int sig)
78     {
79     switch(sig) {
80     case SIGHUP:
81     /* For future use */
82     break;
83    
84     case SIGQUIT:
85     /* save VM context */
86     vm_save_state = TRUE;
87     break;
88    
89     case SIGINT:
90     /* CTRL+C has been pressed */
91     if (hypervisor_mode)
92     hypervisor_stopsig();
93     else {
94     /* In theory, this shouldn't happen thanks to VTTY settings */
95     vm_instance_t *vm;
96    
97     if ((vm = vm_acquire("default")) != NULL) {
98     /* Only forward ctrl-c if user has requested local terminal */
99     if (vm->vtty_con_type == VTTY_TYPE_TERM) {
100     vtty_store_ctrlc(vm->vtty_con);
101     } else {
102     vm_stop(vm);
103     }
104     vm_release(vm);
105     } else {
106     fprintf(stderr,"Error: Cannot acquire instance handle.\n");
107     }
108     }
109     break;
110    
111     default:
112     fprintf(stderr,"Unhandled signal %d\n",sig);
113     }
114     }
115    
116     /* Setups signals */
117     static void setup_signals(void)
118     {
119     struct sigaction act;
120    
121     memset(&act,0,sizeof(act));
122     act.sa_handler = signal_gen_handler;
123     act.sa_flags = SA_RESTART;
124     sigaction(SIGHUP,&act,NULL);
125     sigaction(SIGQUIT,&act,NULL);
126     sigaction(SIGINT,&act,NULL);
127     }
128    
129     /* Create general log file */
130     static void create_log_file(void)
131     {
132     /* Set the default value of the log file name */
133     if (!log_file_name) {
134     if (!(log_file_name = strdup(LOGFILE_DEFAULT_NAME))) {
135     fprintf(stderr,"Unable to set log file name.\n");
136     exit(EXIT_FAILURE);
137     }
138     }
139    
140     if (!(log_file = fopen(log_file_name,"w"))) {
141     fprintf(stderr,"Unable to create log file (%s).\n",strerror(errno));
142     exit(EXIT_FAILURE);
143     }
144     }
145    
146     /* Close general log file */
147     static void close_log_file(void)
148     {
149     if (log_file) fclose(log_file);
150     free(log_file_name);
151    
152     log_file = NULL;
153     log_file_name = NULL;
154     }
155    
156     /* Display the command line use */
157     static void show_usage(int argc,char *argv[],int platform)
158     {
159     u_int def_ram_size,def_rom_size,def_nvram_size;
160     u_int def_conf_reg,def_clock_div;
161 dpavlin 8 u_int def_disk0_size = 0,def_disk1_size = 0;
162 dpavlin 1 u_int def_nm_iomem_size = 0;
163    
164     switch(platform) {
165     case VM_TYPE_C7200:
166     def_ram_size = C7200_DEFAULT_RAM_SIZE;
167     def_rom_size = C7200_DEFAULT_ROM_SIZE;
168     def_nvram_size = C7200_DEFAULT_NVRAM_SIZE;
169     def_conf_reg = C7200_DEFAULT_CONF_REG;
170     def_clock_div = C7200_DEFAULT_CLOCK_DIV;
171     def_disk0_size = C7200_DEFAULT_DISK0_SIZE;
172     def_disk1_size = C7200_DEFAULT_DISK1_SIZE;
173     break;
174     case VM_TYPE_C3600:
175     def_ram_size = C3600_DEFAULT_RAM_SIZE;
176     def_rom_size = C3600_DEFAULT_ROM_SIZE;
177     def_nvram_size = C3600_DEFAULT_NVRAM_SIZE;
178     def_conf_reg = C3600_DEFAULT_CONF_REG;
179     def_clock_div = C3600_DEFAULT_CLOCK_DIV;
180     def_disk0_size = C3600_DEFAULT_DISK0_SIZE;
181     def_disk1_size = C3600_DEFAULT_DISK1_SIZE;
182     def_nm_iomem_size = C3600_DEFAULT_IOMEM_SIZE;
183     break;
184 dpavlin 4 case VM_TYPE_C2691:
185     def_ram_size = C2691_DEFAULT_RAM_SIZE;
186     def_rom_size = C2691_DEFAULT_ROM_SIZE;
187     def_nvram_size = C2691_DEFAULT_NVRAM_SIZE;
188     def_conf_reg = C2691_DEFAULT_CONF_REG;
189     def_clock_div = C2691_DEFAULT_CLOCK_DIV;
190     def_disk0_size = C2691_DEFAULT_DISK0_SIZE;
191     def_disk1_size = C2691_DEFAULT_DISK1_SIZE;
192     def_nm_iomem_size = C2691_DEFAULT_IOMEM_SIZE;
193     break;
194     case VM_TYPE_C3725:
195     def_ram_size = C3725_DEFAULT_RAM_SIZE;
196     def_rom_size = C3725_DEFAULT_ROM_SIZE;
197     def_nvram_size = C3725_DEFAULT_NVRAM_SIZE;
198     def_conf_reg = C3725_DEFAULT_CONF_REG;
199     def_clock_div = C3725_DEFAULT_CLOCK_DIV;
200     def_disk0_size = C3725_DEFAULT_DISK0_SIZE;
201     def_disk1_size = C3725_DEFAULT_DISK1_SIZE;
202     def_nm_iomem_size = C3725_DEFAULT_IOMEM_SIZE;
203     break;
204     case VM_TYPE_C3745:
205     def_ram_size = C3745_DEFAULT_RAM_SIZE;
206     def_rom_size = C3745_DEFAULT_ROM_SIZE;
207     def_nvram_size = C3745_DEFAULT_NVRAM_SIZE;
208     def_conf_reg = C3745_DEFAULT_CONF_REG;
209     def_clock_div = C3745_DEFAULT_CLOCK_DIV;
210     def_disk0_size = C3745_DEFAULT_DISK0_SIZE;
211     def_disk1_size = C3745_DEFAULT_DISK1_SIZE;
212     def_nm_iomem_size = C3745_DEFAULT_IOMEM_SIZE;
213     break;
214 dpavlin 7 case VM_TYPE_C2600:
215     def_ram_size = C2600_DEFAULT_RAM_SIZE;
216     def_rom_size = C2600_DEFAULT_ROM_SIZE;
217     def_nvram_size = C2600_DEFAULT_NVRAM_SIZE;
218     def_conf_reg = C2600_DEFAULT_CONF_REG;
219     def_clock_div = C2600_DEFAULT_CLOCK_DIV;
220     def_disk0_size = C2600_DEFAULT_DISK0_SIZE;
221     def_disk1_size = C2600_DEFAULT_DISK1_SIZE;
222 dpavlin 8 def_nm_iomem_size = C2600_DEFAULT_IOMEM_SIZE;
223 dpavlin 7 break;
224 dpavlin 8 case VM_TYPE_MSFC1:
225     def_ram_size = MSFC1_DEFAULT_RAM_SIZE;
226     def_rom_size = MSFC1_DEFAULT_ROM_SIZE;
227     def_nvram_size = MSFC1_DEFAULT_NVRAM_SIZE;
228     def_conf_reg = MSFC1_DEFAULT_CONF_REG;
229     def_clock_div = MSFC1_DEFAULT_CLOCK_DIV;
230     break;
231 dpavlin 7 case VM_TYPE_PPC32_TEST:
232     def_ram_size = PPC32_VMTEST_DEFAULT_RAM_SIZE;
233 dpavlin 1 default:
234     fprintf(stderr,"show_usage: invalid platform.\n");
235     return;
236     }
237    
238     printf("Usage: %s [options] <ios_image>\n\n",argv[0]);
239    
240     printf("Available options:\n"
241 dpavlin 3 " -H <tcp_port> : Run in hypervisor mode\n\n"
242 dpavlin 4 " -P <platform> : Platform to emulate (7200, 3600, "
243     "2691, 3725 or 3745) "
244 dpavlin 1 "(default: 7200)\n\n"
245     " -l <log_file> : Set logging file (default is %s)\n"
246     " -j : Disable the JIT compiler, very slow\n"
247     " --exec-area <size> : Set the exec area size (default: %d Mb)\n"
248     " --idle-pc <pc> : Set the idle PC (default: disabled)\n"
249     " --timer-itv <val> : Timer IRQ interval check (default: %u)\n"
250     "\n"
251     " -i <instance> : Set instance ID\n"
252     " -r <ram_size> : Set the virtual RAM size (default: %u Mb)\n"
253     " -o <rom_size> : Set the virtual ROM size (default: %u Mb)\n"
254     " -n <nvram_size> : Set the NVRAM size (default: %d Kb)\n"
255     " -c <conf_reg> : Set the configuration register "
256     "(default: 0x%04x)\n"
257     " -m <mac_addr> : Set the MAC address of the chassis\n"
258     " (default: automatically generated)\n"
259     " -C <cfg_file> : Import an IOS configuration file "
260     "into NVRAM\n"
261     " -X : Do not use a file to simulate RAM (faster)\n"
262 dpavlin 4 " -G <ghost_file> : Use a ghost file to simulate RAM\n"
263     " -g <ghost_file> : Generate a ghost RAM file\n"
264 dpavlin 7 " --sparse-mem : Use sparse memory\n"
265 dpavlin 1 " -R <rom_file> : Load an alternate ROM (default: embedded)\n"
266     " -k <clock_div> : Set the clock divisor (default: %d)\n"
267     "\n"
268     " -T <port> : Console is on TCP <port>\n"
269     " -U <si_desc> : Console in on serial interface <si_desc>\n"
270     " (default is on the terminal)\n"
271     "\n"
272     " -A <port> : AUX is on TCP <port>\n"
273     " -B <si_desc> : AUX is on serial interface <si_desc>\n"
274     " (default is no AUX port)\n"
275     "\n"
276     " --disk0 <size> : Set PCMCIA ATA disk0: size "
277     "(default: %u Mb)\n"
278     " --disk1 <size> : Set PCMCIA ATA disk1: size "
279     "(default: %u Mb)\n"
280     "\n",
281     LOGFILE_DEFAULT_NAME,MIPS_EXEC_AREA_SIZE,VM_TIMER_IRQ_CHECK_ITV,
282     def_ram_size,def_rom_size,def_nvram_size,def_conf_reg,
283     def_clock_div,def_disk0_size,def_disk1_size);
284    
285     switch(platform) {
286     case VM_TYPE_C7200:
287     printf(" -t <npe_type> : Select NPE type (default: \"%s\")\n"
288     " -M <midplane> : Select Midplane (\"std\" or \"vxr\")\n"
289     " -p <pa_desc> : Define a Port Adapter\n"
290     " -s <pa_nio> : Bind a Network IO interface to a "
291     "Port Adapter\n",
292     C7200_DEFAULT_NPE_TYPE);
293     break;
294    
295     case VM_TYPE_C3600:
296     printf(" -t <chassis_type> : Select Chassis type "
297     "(default: \"%s\")\n"
298     " --iomem-size <val> : IO memory (in percents, default: %u)\n"
299     " -p <nm_desc> : Define a Network Module\n"
300     " -s <nm_nio> : Bind a Network IO interface to a "
301     "Network Module\n",
302     C3600_DEFAULT_CHASSIS,def_nm_iomem_size);
303     break;
304 dpavlin 4
305     case VM_TYPE_C2691:
306     printf(" --iomem-size <val> : IO memory (in percents, default: %u)\n"
307     " -p <nm_desc> : Define a Network Module\n"
308     " -s <nm_nio> : Bind a Network IO interface to a "
309     "Network Module\n",
310     def_nm_iomem_size);
311     break;
312    
313     case VM_TYPE_C3725:
314     printf(" --iomem-size <val> : IO memory (in percents, default: %u)\n"
315     " -p <nm_desc> : Define a Network Module\n"
316     " -s <nm_nio> : Bind a Network IO interface to a "
317     "Network Module\n",
318     def_nm_iomem_size);
319     break;
320    
321     case VM_TYPE_C3745:
322     printf(" --iomem-size <val> : IO memory (in percents, default: %u)\n"
323     " -p <nm_desc> : Define a Network Module\n"
324     " -s <nm_nio> : Bind a Network IO interface to a "
325     "Network Module\n",
326     def_nm_iomem_size);
327     break;
328 dpavlin 7
329     case VM_TYPE_C2600:
330     printf(" --iomem-size <val> : IO memory (in percents, default: %u)\n"
331     " -p <nm_desc> : Define a Network Module\n"
332     " -s <nm_nio> : Bind a Network IO interface to a "
333     "Network Module\n",
334     def_nm_iomem_size);
335     break;
336 dpavlin 8
337     case VM_TYPE_MSFC1:
338     printf(" -s <pa_nio> : Bind a Network IO interface to a "
339     "Port Adapter\n");
340     break;
341    
342 dpavlin 1 }
343    
344     printf("\n"
345     #if DEBUG_SYM_TREE
346     " -S <sym_file> : Load a symbol file\n"
347     #endif
348     " -a <cfg_file> : Virtual ATM switch configuration file\n"
349     " -f <cfg_file> : Virtual Frame-Relay switch configuration "
350     "file\n"
351     " -E <cfg_file> : Virtual Ethernet switch configuration file\n"
352     " -b <cfg_file> : Virtual bridge configuration file\n"
353     " -e : Show network device list of the "
354     "host machine\n"
355     "\n");
356    
357     printf("<si_desc> format:\n"
358     " \"device{:baudrate{:databits{:parity{:stopbits{:hwflow}}}}}}\"\n"
359     "\n");
360    
361     switch(platform) {
362     case VM_TYPE_C7200:
363     printf("<pa_desc> format:\n"
364     " \"slot:pa_driver\"\n"
365     "\n");
366    
367     printf("<pa_nio> format:\n"
368     " \"slot:port:netio_type{:netio_parameters}\"\n"
369     "\n");
370    
371     /* Show the possible NPE drivers */
372     c7200_npe_show_drivers();
373    
374     /* Show the possible PA drivers */
375     c7200_pa_show_drivers();
376     break;
377    
378     case VM_TYPE_C3600:
379     printf("<nm_desc> format:\n"
380     " \"slot:nm_driver\"\n"
381     "\n");
382    
383     printf("<nm_nio> format:\n"
384     " \"slot:port:netio_type{:netio_parameters}\"\n"
385     "\n");
386    
387     /* Show the possible chassis types for C3600 platform */
388     c3600_chassis_show_drivers();
389    
390 dpavlin 4 /* Show the possible NM drivers */
391 dpavlin 1 c3600_nm_show_drivers();
392     break;
393 dpavlin 4
394     case VM_TYPE_C2691:
395     printf("<nm_desc> format:\n"
396     " \"slot:nm_driver\"\n"
397     "\n");
398    
399     printf("<nm_nio> format:\n"
400     " \"slot:port:netio_type{:netio_parameters}\"\n"
401     "\n");
402    
403     /* Show the possible NM drivers */
404     c2691_nm_show_drivers();
405     break;
406    
407     case VM_TYPE_C3725:
408     printf("<nm_desc> format:\n"
409     " \"slot:nm_driver\"\n"
410     "\n");
411    
412     printf("<nm_nio> format:\n"
413     " \"slot:port:netio_type{:netio_parameters}\"\n"
414     "\n");
415    
416     /* Show the possible NM drivers */
417     c3725_nm_show_drivers();
418     break;
419    
420     case VM_TYPE_C3745:
421     printf("<nm_desc> format:\n"
422     " \"slot:nm_driver\"\n"
423     "\n");
424    
425     printf("<nm_nio> format:\n"
426     " \"slot:port:netio_type{:netio_parameters}\"\n"
427     "\n");
428    
429     /* Show the possible NM drivers */
430     c3745_nm_show_drivers();
431     break;
432 dpavlin 7
433     case VM_TYPE_C2600:
434     printf("<nm_desc> format:\n"
435     " \"slot:nm_driver\"\n"
436     "\n");
437    
438     printf("<nm_nio> format:\n"
439     " \"slot:port:netio_type{:netio_parameters}\"\n"
440     "\n");
441    
442     /* Show the possible chassis types for C2600 platform */
443     c2600_mainboard_show_drivers();
444    
445     /* Show the possible NM drivers */
446     c2600_nm_show_drivers();
447     break;
448 dpavlin 1 }
449    
450     /* Show the possible NETIO types */
451     netio_show_types();
452     }
453    
454     /* Find an option in the command line */
455     static char *cli_find_option(int argc,char *argv[],char *opt)
456     {
457     int i;
458    
459     for(i=1;i<argc;i++) {
460     if (!strncmp(argv[i],opt,2)) {
461     if (argv[i][2] != 0)
462     return(&argv[i][2]);
463     else {
464     if (argv[i+1] != NULL)
465     return(argv[i+1]);
466     else {
467     fprintf(stderr,"Error: option '%s': no argument specified.\n",
468     opt);
469     exit(EXIT_FAILURE);
470     }
471     }
472     }
473     }
474    
475     return NULL;
476     }
477    
478     /* Determine the platform (Cisco 3600, 7200). Default is Cisco 7200 */
479     static int cli_get_platform_type(int argc,char *argv[])
480     {
481     int vm_type = VM_TYPE_C7200;
482     char *str;
483    
484     if ((str = cli_find_option(argc,argv,"-P"))) {
485     if (!strcmp(str,"3600"))
486     vm_type = VM_TYPE_C3600;
487     else if (!strcmp(str,"7200"))
488     vm_type = VM_TYPE_C7200;
489 dpavlin 4 else if (!strcmp(str,"2691"))
490     vm_type = VM_TYPE_C2691;
491     else if (!strcmp(str,"3725"))
492     vm_type = VM_TYPE_C3725;
493     else if (!strcmp(str,"3745"))
494     vm_type = VM_TYPE_C3745;
495 dpavlin 7 else if (!strcmp(str,"2600"))
496     vm_type = VM_TYPE_C2600;
497 dpavlin 8 else if (!strcmp(str,"MSFC1"))
498     vm_type = VM_TYPE_MSFC1;
499 dpavlin 7 else if (!strcmp(str,"PPC32_TEST"))
500     vm_type = VM_TYPE_PPC32_TEST;
501 dpavlin 1 else
502     fprintf(stderr,"Invalid platform type '%s'\n",str);
503     }
504    
505     return(vm_type);
506     }
507    
508     /* Command Line long options */
509     #define OPT_DISK0_SIZE 0x100
510     #define OPT_DISK1_SIZE 0x101
511     #define OPT_EXEC_AREA 0x102
512     #define OPT_IDLE_PC 0x103
513     #define OPT_TIMER_ITV 0x104
514     #define OPT_VM_DEBUG 0x105
515     #define OPT_IOMEM_SIZE 0x106
516 dpavlin 7 #define OPT_SPARSE_MEM 0x107
517 dpavlin 1
518     static struct option cmd_line_lopts[] = {
519     { "disk0" , 1, NULL, OPT_DISK0_SIZE },
520     { "disk1" , 1, NULL, OPT_DISK1_SIZE },
521     { "exec-area" , 1, NULL, OPT_EXEC_AREA },
522     { "idle-pc" , 1, NULL, OPT_IDLE_PC },
523     { "timer-itv" , 1, NULL, OPT_TIMER_ITV },
524     { "vm-debug" , 1, NULL, OPT_VM_DEBUG },
525     { "iomem-size" , 1, NULL, OPT_IOMEM_SIZE },
526 dpavlin 7 { "sparse-mem" , 0, NULL, OPT_SPARSE_MEM },
527 dpavlin 1 { NULL , 0, NULL, 0 },
528     };
529    
530     /* Parse specific options for the Cisco 7200 platform */
531     static int cli_parse_c7200_options(vm_instance_t *vm,int option)
532     {
533     c7200_t *router;
534    
535     router = VM_C7200(vm);
536    
537     switch(option) {
538     /* NPE type */
539     case 't':
540     c7200_npe_set_type(router,optarg);
541     break;
542    
543     /* Midplane type */
544     case 'M':
545     c7200_midplane_set_type(router,optarg);
546     break;
547    
548     /* Set the base MAC address */
549     case 'm':
550     if (!c7200_midplane_set_mac_addr(router,optarg))
551     printf("MAC address set to '%s'.\n",optarg);
552     break;
553    
554     /* PA settings */
555     case 'p':
556     return(c7200_cmd_pa_create(router,optarg));
557    
558     /* PA NIO settings */
559     case 's':
560     return(c7200_cmd_add_nio(router,optarg));
561    
562     /* Unknown option */
563     default:
564     return(-1);
565     }
566    
567     return(0);
568     }
569    
570     /* Parse specific options for the Cisco 3600 platform */
571     static int cli_parse_c3600_options(vm_instance_t *vm,int option)
572     {
573     c3600_t *router;
574    
575     router = VM_C3600(vm);
576    
577     switch(option) {
578     /* chassis type */
579     case 't':
580     c3600_chassis_set_type(router,optarg);
581     break;
582    
583     /* IO memory reserved for NMs (in percents!) */
584     case OPT_IOMEM_SIZE:
585     router->nm_iomem_size = 0x8000 | atoi(optarg);
586     break;
587    
588     /* NM settings */
589     case 'p':
590     return(c3600_cmd_nm_create(router,optarg));
591    
592     /* NM NIO settings */
593     case 's':
594     return(c3600_cmd_add_nio(router,optarg));
595    
596     /* Unknown option */
597     default:
598     return(-1);
599     }
600    
601     return(0);
602     }
603    
604 dpavlin 4 /* Parse specific options for the Cisco 2691 platform */
605     static int cli_parse_c2691_options(vm_instance_t *vm,int option)
606     {
607     c2691_t *router;
608    
609     router = VM_C2691(vm);
610    
611     switch(option) {
612     /* IO memory reserved for NMs (in percents!) */
613     case OPT_IOMEM_SIZE:
614     router->nm_iomem_size = 0x8000 | atoi(optarg);
615     break;
616    
617     /* NM settings */
618     case 'p':
619     return(c2691_cmd_nm_create(router,optarg));
620    
621     /* NM NIO settings */
622     case 's':
623     return(c2691_cmd_add_nio(router,optarg));
624    
625     /* Unknown option */
626     default:
627     return(-1);
628     }
629    
630     return(0);
631     }
632    
633     /* Parse specific options for the Cisco 3725 platform */
634     static int cli_parse_c3725_options(vm_instance_t *vm,int option)
635     {
636     c3725_t *router;
637    
638     router = VM_C3725(vm);
639    
640     switch(option) {
641     /* IO memory reserved for NMs (in percents!) */
642     case OPT_IOMEM_SIZE:
643     router->nm_iomem_size = 0x8000 | atoi(optarg);
644     break;
645    
646     /* NM settings */
647     case 'p':
648     return(c3725_cmd_nm_create(router,optarg));
649    
650     /* NM NIO settings */
651     case 's':
652     return(c3725_cmd_add_nio(router,optarg));
653    
654     /* Unknown option */
655     default:
656     return(-1);
657     }
658    
659     return(0);
660     }
661    
662     /* Parse specific options for the Cisco 3745 platform */
663     static int cli_parse_c3745_options(vm_instance_t *vm,int option)
664     {
665     c3745_t *router;
666    
667     router = VM_C3745(vm);
668    
669     switch(option) {
670     /* IO memory reserved for NMs (in percents!) */
671     case OPT_IOMEM_SIZE:
672     router->nm_iomem_size = 0x8000 | atoi(optarg);
673     break;
674    
675     /* NM settings */
676     case 'p':
677     return(c3745_cmd_nm_create(router,optarg));
678    
679     /* NM NIO settings */
680     case 's':
681     return(c3745_cmd_add_nio(router,optarg));
682    
683     /* Unknown option */
684     default:
685     return(-1);
686     }
687    
688     return(0);
689     }
690    
691 dpavlin 7 /* Parse specific options for the Cisco 2600 platform */
692     static int cli_parse_c2600_options(vm_instance_t *vm,int option)
693     {
694     c2600_t *router;
695    
696     router = VM_C2600(vm);
697    
698     switch(option) {
699     /* IO memory reserved for NMs (in percents!) */
700     case OPT_IOMEM_SIZE:
701     router->nm_iomem_size = 0x8000 | atoi(optarg);
702     break;
703    
704     /* Mainboard type */
705     case 't':
706     c2600_mainboard_set_type(router,optarg);
707     break;
708    
709     /* NM settings */
710     case 'p':
711     return(c2600_cmd_nm_create(router,optarg));
712    
713     /* NM NIO settings */
714     case 's':
715     return(c2600_cmd_add_nio(router,optarg));
716    
717     /* Unknown option */
718     default:
719     return(-1);
720     }
721    
722     return(0);
723     }
724    
725 dpavlin 8 /* Parse specific options for the MSFC1 platform */
726     static int cli_parse_msfc1_options(vm_instance_t *vm,int option)
727     {
728     msfc1_t *router;
729    
730     router = VM_MSFC1(vm);
731    
732     switch(option) {
733     /* PA NIO settings */
734     case 's':
735     return(msfc1_cmd_add_nio(router,optarg));
736    
737     /* Unknown option */
738     default:
739     return(-1);
740     }
741    
742     return(0);
743     }
744    
745 dpavlin 1 /* Create a router instance */
746     static vm_instance_t *cli_create_instance(char *name,int platform_type,
747     int instance_id)
748     {
749 dpavlin 7 vm_instance_t *vm;
750 dpavlin 1 c7200_t *c7200;
751     c3600_t *c3600;
752 dpavlin 4 c2691_t *c2691;
753     c3725_t *c3725;
754     c3745_t *c3745;
755 dpavlin 7 c2600_t *c2600;
756 dpavlin 8 msfc1_t *msfc1;
757 dpavlin 1
758     switch(platform_type) {
759     case VM_TYPE_C7200:
760     if (!(c7200 = c7200_create_instance(name,instance_id))) {
761     fprintf(stderr,"C7200: unable to create instance!\n");
762     return NULL;
763     }
764     return(c7200->vm);
765    
766     case VM_TYPE_C3600:
767     if (!(c3600 = c3600_create_instance(name,instance_id))) {
768     fprintf(stderr,"C3600: unable to create instance!\n");
769     return NULL;
770     }
771     return(c3600->vm);
772    
773 dpavlin 4 case VM_TYPE_C2691:
774     if (!(c2691 = c2691_create_instance(name,instance_id))) {
775     fprintf(stderr,"C2691: unable to create instance!\n");
776     return NULL;
777     }
778     return(c2691->vm);
779    
780     case VM_TYPE_C3725:
781     if (!(c3725 = c3725_create_instance(name,instance_id))) {
782     fprintf(stderr,"C3725: unable to create instance!\n");
783     return NULL;
784     }
785     return(c3725->vm);
786    
787     case VM_TYPE_C3745:
788     if (!(c3745 = c3745_create_instance(name,instance_id))) {
789     fprintf(stderr,"C3745: unable to create instance!\n");
790     return NULL;
791     }
792     return(c3745->vm);
793    
794 dpavlin 7 case VM_TYPE_C2600:
795     if (!(c2600 = c2600_create_instance(name,instance_id))) {
796     fprintf(stderr,"C2600: unable to create instance!\n");
797     return NULL;
798     }
799     return(c2600->vm);
800    
801 dpavlin 8 case VM_TYPE_MSFC1:
802     if (!(msfc1 = msfc1_create_instance(name,instance_id))) {
803     fprintf(stderr,"MSFC1: unable to create instance!\n");
804     return NULL;
805     }
806     return(msfc1->vm);
807    
808 dpavlin 7 case VM_TYPE_PPC32_TEST:
809     if (!(vm = ppc32_vmtest_create_instance(name,instance_id))) {
810     fprintf(stderr,"PPC32_TEST: unable to create instance!\n");
811     return NULL;
812     }
813     return(vm);
814    
815 dpavlin 1 default:
816     fprintf(stderr,"Unknown platform type '%d'!\n",platform_type);
817     return NULL;
818     }
819     }
820    
821     /* Parse the command line */
822     static int parse_std_cmd_line(int argc,char *argv[],int *platform)
823     {
824     char *options_list =
825 dpavlin 4 "r:o:n:c:m:l:C:i:jt:p:s:k:T:U:A:B:a:f:E:b:S:R:M:eXP:N:G:g:";
826 dpavlin 1 vm_instance_t *vm;
827     int instance_id;
828     int res,option;
829     char *str;
830    
831     /* Get the instance ID */
832     instance_id = 0;
833    
834     /* Use the old VM file naming type */
835     vm_file_naming_type = 1;
836    
837     if ((str = cli_find_option(argc,argv,"-i"))) {
838     instance_id = atoi(str);
839     printf("Instance ID set to %d.\n",instance_id);
840     }
841    
842     if ((str = cli_find_option(argc,argv,"-N")))
843     vm_file_naming_type = atoi(str);
844    
845     /* Get the platform type */
846     *platform = cli_get_platform_type(argc,argv);
847    
848     /* Create the default instance */
849     if (!(vm = cli_create_instance("default",*platform,instance_id)))
850     exit(EXIT_FAILURE);
851    
852     opterr = 0;
853    
854     while((option = getopt_long(argc,argv,options_list,
855     cmd_line_lopts,NULL)) != -1)
856     {
857     switch(option)
858     {
859     /* Instance ID (already managed) */
860     case 'i':
861     break;
862    
863     /* Platform (already managed) */
864     case 'P':
865     break;
866    
867     /* RAM size */
868     case 'r':
869     vm->ram_size = strtol(optarg, NULL, 10);
870     printf("Virtual RAM size set to %d MB.\n",vm->ram_size);
871     break;
872    
873     /* ROM size */
874     case 'o':
875     vm->rom_size = strtol(optarg, NULL, 10);
876     printf("Virtual ROM size set to %d MB.\n",vm->rom_size);
877     break;
878    
879     /* NVRAM size */
880     case 'n':
881     vm->nvram_size = strtol(optarg, NULL, 10);
882     printf("NVRAM size set to %d KB.\n",vm->nvram_size);
883     break;
884    
885     /* Execution area size */
886     case OPT_EXEC_AREA:
887     vm->exec_area_size = atoi(optarg);
888     break;
889    
890     /* PCMCIA disk0 size */
891     case OPT_DISK0_SIZE:
892     vm->pcmcia_disk_size[0] = atoi(optarg);
893     printf("PCMCIA ATA disk0 size set to %u MB.\n",
894     vm->pcmcia_disk_size[0]);
895     break;
896    
897     /* PCMCIA disk1 size */
898     case OPT_DISK1_SIZE:
899     vm->pcmcia_disk_size[1] = atoi(optarg);
900     printf("PCMCIA ATA disk1 size set to %u MB.\n",
901     vm->pcmcia_disk_size[1]);
902     break;
903    
904     /* Config Register */
905     case 'c':
906     vm->conf_reg_setup = strtol(optarg, NULL, 0);
907     printf("Config. Register set to 0x%x.\n",vm->conf_reg_setup);
908     break;
909    
910     /* IOS configuration file */
911     case 'C':
912     vm_ios_set_config(vm,optarg);
913     break;
914    
915     /* Use physical memory to emulate RAM (no-mapped file) */
916     case 'X':
917     vm->ram_mmap = 0;
918     break;
919    
920 dpavlin 4 /* Use a ghost file to simulate RAM */
921     case 'G':
922     vm->ghost_ram_filename = strdup(optarg);
923     vm->ghost_status = VM_GHOST_RAM_USE;
924     break;
925    
926     /* Generate a ghost RAM image */
927     case 'g':
928     vm->ghost_ram_filename = strdup(optarg);
929     vm->ghost_status = VM_GHOST_RAM_GENERATE;
930     break;
931    
932 dpavlin 7 /* Use sparse memory */
933     case OPT_SPARSE_MEM:
934     vm->sparse_mem = TRUE;
935     break;
936    
937 dpavlin 1 /* Alternate ROM */
938     case 'R':
939     vm->rom_filename = optarg;
940     break;
941    
942     /* Idle PC */
943     case OPT_IDLE_PC:
944     vm->idle_pc = strtoull(optarg,NULL,0);
945     printf("Idle PC set to 0x%llx.\n",vm->idle_pc);
946     break;
947    
948     /* Timer IRQ check interval */
949     case OPT_TIMER_ITV:
950     vm->timer_irq_check_itv = atoi(optarg);
951     break;
952    
953     /* Clock divisor */
954     case 'k':
955     vm->clock_divisor = atoi(optarg);
956    
957     if (!vm->clock_divisor) {
958     fprintf(stderr,"Invalid Clock Divisor specified!\n");
959     exit(EXIT_FAILURE);
960     }
961    
962     printf("Using a clock divisor of %d.\n",vm->clock_divisor);
963     break;
964    
965     /* Disable JIT */
966     case 'j':
967     vm->jit_use = FALSE;
968     break;
969    
970     /* VM debug level */
971     case OPT_VM_DEBUG:
972     vm->debug_level = atoi(optarg);
973     break;
974    
975     /* Log file */
976     case 'l':
977     if (!(log_file_name = strdup(optarg))) {
978     fprintf(stderr,"Unable to set log file name.\n");
979     exit(EXIT_FAILURE);
980     }
981     printf("Log file: writing to %s\n",log_file_name);
982     break;
983    
984     #if DEBUG_SYM_TREE
985     /* Symbol file */
986     case 'S':
987     vm->sym_filename = strdup(optarg);
988     break;
989     #endif
990    
991     /* TCP server for Console Port */
992     case 'T':
993     vm->vtty_con_type = VTTY_TYPE_TCP;
994     vm->vtty_con_tcp_port = atoi(optarg);
995     break;
996    
997     /* Serial interface for Console port */
998     case 'U':
999     vm->vtty_con_type = VTTY_TYPE_SERIAL;
1000     if (vtty_parse_serial_option(&vm->vtty_con_serial_option,optarg)) {
1001     fprintf(stderr,
1002     "Invalid Console serial interface descriptor!\n");
1003     exit(EXIT_FAILURE);
1004     }
1005     break;
1006    
1007     /* TCP server for AUX Port */
1008     case 'A':
1009     vm->vtty_aux_type = VTTY_TYPE_TCP;
1010     vm->vtty_aux_tcp_port = atoi(optarg);
1011     break;
1012    
1013     /* Serial interface for AUX port */
1014     case 'B':
1015     vm->vtty_aux_type = VTTY_TYPE_SERIAL;
1016     if (vtty_parse_serial_option(&vm->vtty_aux_serial_option,optarg)) {
1017     fprintf(stderr,"Invalid AUX serial interface descriptor!\n");
1018     exit(EXIT_FAILURE);
1019     }
1020     break;
1021    
1022     /* Virtual ATM switch */
1023     case 'a':
1024     if (atmsw_start(optarg) == -1)
1025     exit(EXIT_FAILURE);
1026     break;
1027    
1028     /* Virtual Frame-Relay switch */
1029     case 'f':
1030     if (frsw_start(optarg) == -1)
1031     exit(EXIT_FAILURE);
1032     break;
1033    
1034     /* Virtual Ethernet switch */
1035     case 'E':
1036     if (ethsw_start(optarg) == -1)
1037     exit(EXIT_FAILURE);
1038     break;
1039    
1040     /* Virtual bridge */
1041     case 'b':
1042     if (netio_bridge_start(optarg) == -1)
1043     exit(EXIT_FAILURE);
1044     break;
1045    
1046     #ifdef GEN_ETH
1047     /* Ethernet device list */
1048     case 'e':
1049     gen_eth_show_dev_list();
1050     exit(EXIT_SUCCESS);
1051     #endif
1052    
1053     /* Oops ! */
1054     case '?':
1055     show_usage(argc,argv,*platform);
1056     exit(EXIT_FAILURE);
1057    
1058     /* Parse options specific to the platform */
1059     default:
1060     res = 0;
1061    
1062     switch(vm->type) {
1063     case VM_TYPE_C7200:
1064     res = cli_parse_c7200_options(vm,option);
1065     break;
1066     case VM_TYPE_C3600:
1067     res = cli_parse_c3600_options(vm,option);
1068 dpavlin 4 break;
1069     case VM_TYPE_C2691:
1070     res = cli_parse_c2691_options(vm,option);
1071 dpavlin 1 break;
1072 dpavlin 4 case VM_TYPE_C3725:
1073     res = cli_parse_c3725_options(vm,option);
1074     break;
1075     case VM_TYPE_C3745:
1076     res = cli_parse_c3745_options(vm,option);
1077     break;
1078 dpavlin 7 case VM_TYPE_C2600:
1079     res = cli_parse_c2600_options(vm,option);
1080     break;
1081 dpavlin 8 case VM_TYPE_MSFC1:
1082     res = cli_parse_msfc1_options(vm,option);
1083     break;
1084 dpavlin 1 }
1085    
1086     if (res == -1)
1087     exit(EXIT_FAILURE);
1088     }
1089     }
1090    
1091     /* Last argument, this is the IOS filename */
1092     if (optind == (argc - 1)) {
1093     /* setting IOS image file */
1094     vm_ios_set_image(vm,argv[optind]);
1095     printf("IOS image file: %s\n\n",vm->ios_image);
1096     } else {
1097     /* IOS missing */
1098     fprintf(stderr,"Please specify an IOS image filename\n");
1099     show_usage(argc,argv,*platform);
1100     exit(EXIT_FAILURE);
1101     }
1102    
1103     vm_release(vm);
1104     return(0);
1105     }
1106    
1107     /*
1108     * Run in hypervisor mode with a config file if the "-H" option
1109     * is present in command line.
1110     */
1111     static int run_hypervisor(int argc,char *argv[])
1112     {
1113     char *options_list = "H:l:hN:";
1114     int i,option;
1115    
1116     for(i=1;i<argc;i++)
1117     if (!strcmp(argv[i],"-H")) {
1118     hypervisor_mode = 1;
1119     break;
1120     }
1121    
1122     /* standard mode with one instance */
1123     if (!hypervisor_mode)
1124     return(FALSE);
1125    
1126     opterr = 0;
1127     while((option = getopt(argc,argv,options_list)) != -1) {
1128     switch(option)
1129     {
1130     /* Hypervisor TCP port */
1131     case 'H':
1132     hypervisor_tcp_port = atoi(optarg);
1133     break;
1134    
1135     /* Log file */
1136     case 'l':
1137     if (!(log_file_name = malloc(strlen(optarg)+1))) {
1138     fprintf(stderr,"Unable to set log file name.\n");
1139     exit(EXIT_FAILURE);
1140     }
1141     strcpy(log_file_name, optarg);
1142     printf("Log file: writing to %s\n",log_file_name);
1143     break;
1144    
1145     /* VM file naming type */
1146     case 'N':
1147     vm_file_naming_type = atoi(optarg);
1148     break;
1149    
1150     /* Oops ! */
1151     case '?':
1152     show_usage(argc,argv,VM_TYPE_C7200);
1153     exit(EXIT_FAILURE);
1154     }
1155     }
1156    
1157     return(TRUE);
1158     }
1159    
1160     /* Delete all objects */
1161     void dynamips_reset(void)
1162     {
1163     printf("Shutdown in progress...\n");
1164    
1165 dpavlin 4 /* Delete all virtual router instances */
1166 dpavlin 1 c7200_delete_all_instances();
1167     c3600_delete_all_instances();
1168 dpavlin 4 c2691_delete_all_instances();
1169     c3725_delete_all_instances();
1170     c3745_delete_all_instances();
1171 dpavlin 7 c2600_delete_all_instances();
1172 dpavlin 8 msfc1_delete_all_instances();
1173 dpavlin 7 ppc32_vmtest_delete_all_instances();
1174 dpavlin 1
1175     /* Delete ATM and Frame-Relay switches + bridges */
1176     netio_bridge_delete_all();
1177     atmsw_delete_all();
1178     frsw_delete_all();
1179     ethsw_delete_all();
1180    
1181     /* Delete all NIO descriptors */
1182     netio_delete_all();
1183    
1184     printf("Shutdown completed.\n");
1185     }
1186    
1187     int main(int argc,char *argv[])
1188     {
1189     vm_instance_t *vm;
1190     int platform,res;
1191    
1192     /* Default emulation: Cisco 7200 */
1193     platform = VM_TYPE_C7200;
1194    
1195     #ifdef PROFILE
1196     atexit(profiler_savestat);
1197     #endif
1198    
1199 dpavlin 7 printf("Cisco Router Simulation Platform (version %s)\n",sw_version);
1200     printf("Copyright (c) 2005-2007 Christophe Fillot.\n");
1201 dpavlin 4 printf("Build date: %s %s\n\n",__DATE__,__TIME__);
1202 dpavlin 1
1203 dpavlin 3 /* Initialize timers */
1204     timer_init();
1205    
1206 dpavlin 1 /* Initialize object registry */
1207     registry_init();
1208    
1209     /* Initialize ATM module (for HEC checksums) */
1210     atm_init();
1211    
1212     /* Initialize CRC functions */
1213     crc_init();
1214    
1215     /* Initialize NetIO code */
1216     netio_rxl_init();
1217    
1218     /* Initialize NetIO packet filters */
1219     netio_filter_load_all();
1220    
1221     /* Initialize VTTY code */
1222     vtty_init();
1223    
1224     /* Parse standard command line */
1225     if (!run_hypervisor(argc,argv))
1226     parse_std_cmd_line(argc,argv,&platform);
1227    
1228     /* Create general log file */
1229     create_log_file();
1230    
1231     /* Periodic tasks initialization */
1232     if (ptask_init(0) == -1)
1233     exit(EXIT_FAILURE);
1234    
1235     /* Create instruction lookup tables */
1236     mips64_jit_create_ilt();
1237     mips64_exec_create_ilt();
1238 dpavlin 7 ppc32_jit_create_ilt();
1239     ppc32_exec_create_ilt();
1240 dpavlin 1
1241     setup_signals();
1242    
1243     if (!hypervisor_mode) {
1244     /* Initialize the default instance */
1245     vm = vm_acquire("default");
1246     assert(vm != NULL);
1247    
1248     switch(platform) {
1249     case VM_TYPE_C7200:
1250     res = c7200_init_instance(VM_C7200(vm));
1251     break;
1252     case VM_TYPE_C3600:
1253     res = c3600_init_instance(VM_C3600(vm));
1254 dpavlin 4 break;
1255     case VM_TYPE_C2691:
1256     res = c2691_init_instance(VM_C2691(vm));
1257 dpavlin 1 break;
1258 dpavlin 4 case VM_TYPE_C3725:
1259     res = c3725_init_instance(VM_C3725(vm));
1260     break;
1261     case VM_TYPE_C3745:
1262     res = c3745_init_instance(VM_C3745(vm));
1263     break;
1264 dpavlin 7 case VM_TYPE_C2600:
1265     res = c2600_init_instance(VM_C2600(vm));
1266     break;
1267 dpavlin 8 case VM_TYPE_MSFC1:
1268     res = msfc1_init_instance(VM_MSFC1(vm));
1269     break;
1270 dpavlin 7 case VM_TYPE_PPC32_TEST:
1271     res = ppc32_vmtest_init_instance(vm);
1272     break;
1273 dpavlin 1 default:
1274     res = -1;
1275     }
1276    
1277     if (res == -1) {
1278     fprintf(stderr,"Unable to initialize router instance.\n");
1279     exit(EXIT_FAILURE);
1280     }
1281    
1282 dpavlin 5 #if (DEBUG_INSN_PERF_CNT > 0) || (DEBUG_BLOCK_PERF_CNT > 0)
1283 dpavlin 1 {
1284 dpavlin 7 m_uint64_t counter,prev = 0,delta;
1285 dpavlin 1 while(vm->status == VM_STATUS_RUNNING) {
1286 dpavlin 7 counter = cpu_get_perf_counter(vm->boot_cpu);
1287     delta = counter - prev;
1288     prev = counter;
1289 dpavlin 1 printf("delta = %llu\n",delta);
1290     sleep(1);
1291     }
1292     }
1293     #else
1294     /* Start instance monitoring */
1295     vm_monitor(vm);
1296     #endif
1297    
1298     /* Free resources used by instance */
1299     vm_release(vm);
1300     } else {
1301     hypervisor_tcp_server(hypervisor_tcp_port);
1302     }
1303    
1304     dynamips_reset();
1305     close_log_file();
1306     return(0);
1307     }

  ViewVC Help
Powered by ViewVC 1.1.26