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