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