/[dynamips]/upstream/dynamips-0.2.7-RC3/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

Contents of /upstream/dynamips-0.2.7-RC3/dynamips.c

Parent Directory Parent Directory | Revision Log Revision Log


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

1 /*
2 * Cisco router simulation platform.
3 * 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 #include "cpu.h"
25 #include "mips64_exec.h"
26 #include "mips64_jit.h"
27 #include "ppc32_exec.h"
28 #include "ppc32_jit.h"
29 #include "dev_c7200.h"
30 #include "dev_c3600.h"
31 #include "dev_c2691.h"
32 #include "dev_c3725.h"
33 #include "dev_c3745.h"
34 #include "dev_c2600.h"
35 #include "dev_msfc1.h"
36 #include "ppc32_vmtest.h"
37 #include "dev_vtty.h"
38 #include "ptask.h"
39 #include "timer.h"
40 #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 /* Software version tag */
63 const char *sw_version_tag = "2007042500";
64
65 /* 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 u_int def_disk0_size = 0,def_disk1_size = 0;
162 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 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 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 def_nm_iomem_size = C2600_DEFAULT_IOMEM_SIZE;
223 break;
224 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 case VM_TYPE_PPC32_TEST:
232 def_ram_size = PPC32_VMTEST_DEFAULT_RAM_SIZE;
233 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 " -H <tcp_port> : Run in hypervisor mode\n\n"
242 " -P <platform> : Platform to emulate (7200, 3600, "
243 "2691, 3725 or 3745) "
244 "(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 " -G <ghost_file> : Use a ghost file to simulate RAM\n"
263 " -g <ghost_file> : Generate a ghost RAM file\n"
264 " --sparse-mem : Use sparse memory\n"
265 " -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
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
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
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 }
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 /* Show the possible NM drivers */
391 c3600_nm_show_drivers();
392 break;
393
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
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 }
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 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 else if (!strcmp(str,"2600"))
496 vm_type = VM_TYPE_C2600;
497 else if (!strcmp(str,"MSFC1"))
498 vm_type = VM_TYPE_MSFC1;
499 else if (!strcmp(str,"PPC32_TEST"))
500 vm_type = VM_TYPE_PPC32_TEST;
501 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 #define OPT_SPARSE_MEM 0x107
517
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 { "sparse-mem" , 0, NULL, OPT_SPARSE_MEM },
527 { 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 /* 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 /* 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 /* 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 /* Create a router instance */
746 static vm_instance_t *cli_create_instance(char *name,int platform_type,
747 int instance_id)
748 {
749 vm_instance_t *vm;
750 c7200_t *c7200;
751 c3600_t *c3600;
752 c2691_t *c2691;
753 c3725_t *c3725;
754 c3745_t *c3745;
755 c2600_t *c2600;
756 msfc1_t *msfc1;
757
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 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 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 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 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 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 "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 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 /* 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 /* Use sparse memory */
933 case OPT_SPARSE_MEM:
934 vm->sparse_mem = TRUE;
935 break;
936
937 /* 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 break;
1069 case VM_TYPE_C2691:
1070 res = cli_parse_c2691_options(vm,option);
1071 break;
1072 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 case VM_TYPE_C2600:
1079 res = cli_parse_c2600_options(vm,option);
1080 break;
1081 case VM_TYPE_MSFC1:
1082 res = cli_parse_msfc1_options(vm,option);
1083 break;
1084 }
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 /* Delete all virtual router instances */
1166 c7200_delete_all_instances();
1167 c3600_delete_all_instances();
1168 c2691_delete_all_instances();
1169 c3725_delete_all_instances();
1170 c3745_delete_all_instances();
1171 c2600_delete_all_instances();
1172 msfc1_delete_all_instances();
1173 ppc32_vmtest_delete_all_instances();
1174
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 printf("Cisco Router Simulation Platform (version %s)\n",sw_version);
1200 printf("Copyright (c) 2005-2007 Christophe Fillot.\n");
1201 printf("Build date: %s %s\n\n",__DATE__,__TIME__);
1202
1203 /* Initialize timers */
1204 timer_init();
1205
1206 /* 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 ppc32_jit_create_ilt();
1239 ppc32_exec_create_ilt();
1240
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 break;
1255 case VM_TYPE_C2691:
1256 res = c2691_init_instance(VM_C2691(vm));
1257 break;
1258 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 case VM_TYPE_C2600:
1265 res = c2600_init_instance(VM_C2600(vm));
1266 break;
1267 case VM_TYPE_MSFC1:
1268 res = msfc1_init_instance(VM_MSFC1(vm));
1269 break;
1270 case VM_TYPE_PPC32_TEST:
1271 res = ppc32_vmtest_init_instance(vm);
1272 break;
1273 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 #if (DEBUG_INSN_PERF_CNT > 0) || (DEBUG_BLOCK_PERF_CNT > 0)
1283 {
1284 m_uint64_t counter,prev = 0,delta;
1285 while(vm->status == VM_STATUS_RUNNING) {
1286 counter = cpu_get_perf_counter(vm->boot_cpu);
1287 delta = counter - prev;
1288 prev = counter;
1289 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