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