1 /*
2 * Cisco router simulation platform.
3 * Copyright (c) 2007 Christophe Fillot (cf@utc.fr)
4 *
5 * Generic Cisco card routines and definitions.
6 */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include <sys/types.h>
13 #include <assert.h>
14
15 #include "cpu.h"
16 #include "vm.h"
17 #include "dynamips.h"
18 #include "memory.h"
19 #include "device.h"
20 #include "cisco_card.h"
21
22 /* Get cisco card type description */
cisco_card_get_type_desc(int dev_type)23 char *cisco_card_get_type_desc(int dev_type)
24 {
25 switch(dev_type) {
26 case CISCO_CARD_TYPE_PA:
27 return("Port Adapter (PA)");
28 case CISCO_CARD_TYPE_NM:
29 return("Network Module (NM)");
30 case CISCO_CARD_TYPE_WIC:
31 return("WAN Interface Card (WIC)");
32 default:
33 return("Unknown");
34 }
35 }
36
37 /* Set EEPROM definition for the specified Cisco card */
cisco_card_set_eeprom(vm_instance_t * vm,struct cisco_card * card,const struct cisco_eeprom * eeprom)38 int cisco_card_set_eeprom(vm_instance_t *vm,struct cisco_card *card,
39 const struct cisco_eeprom *eeprom)
40 {
41 if (!eeprom)
42 return(0);
43
44 if (cisco_eeprom_copy(&card->eeprom,eeprom) == -1) {
45 vm_error(vm,"cisco_card_set_eeprom: no memory (eeprom=%p).\n",eeprom);
46 return(-1);
47 }
48
49 return(0);
50 }
51
52 /* Unset EEPROM definition */
cisco_card_unset_eeprom(struct cisco_card * card)53 int cisco_card_unset_eeprom(struct cisco_card *card)
54 {
55 cisco_eeprom_free(&card->eeprom);
56 return(0);
57 }
58
59 /* Check if a card has a valid EEPROM defined */
cisco_card_check_eeprom(struct cisco_card * card)60 int cisco_card_check_eeprom(struct cisco_card *card)
61 {
62 return(cisco_eeprom_valid(&card->eeprom));
63 }
64
65 /* Create a card structure */
cisco_card_create(u_int card_type)66 static inline struct cisco_card *cisco_card_create(u_int card_type)
67 {
68 struct cisco_card *card;
69
70 if ((card = malloc(sizeof(*card))) != NULL) {
71 memset(card,0,sizeof(*card));
72 card->card_type = card_type;
73 }
74
75 return card;
76 }
77
78 /* Find a NIO binding */
79 static struct cisco_nio_binding *
cisco_card_find_nio_binding(struct cisco_card * card,u_int port_id)80 cisco_card_find_nio_binding(struct cisco_card *card,u_int port_id)
81 {
82 struct cisco_nio_binding *nb;
83
84 if (!card)
85 return NULL;
86
87 for(nb=card->nio_list;nb;nb=nb->next)
88 if (nb->port_id == port_id)
89 return nb;
90
91 return NULL;
92 }
93
94 /* Remove all NIO bindings */
95 static void
cisco_card_remove_all_nio_bindings(vm_instance_t * vm,struct cisco_card * card)96 cisco_card_remove_all_nio_bindings(vm_instance_t *vm,struct cisco_card *card)
97 {
98 struct cisco_nio_binding *nb,*next;
99
100 for(nb=card->nio_list;nb;nb=next) {
101 next = nb->next;
102
103 /* tell the slot driver to stop using this NIO */
104 if (card->driver)
105 card->driver->card_unset_nio(vm,card,nb->port_id);
106
107 /* unreference NIO object */
108 netio_release(nb->nio->name);
109 free(nb);
110 }
111
112 card->nio_list = NULL;
113 }
114
115 /* Enable all NIO for the specified card */
116 static inline
cisco_card_enable_all_nio(vm_instance_t * vm,struct cisco_card * card)117 void cisco_card_enable_all_nio(vm_instance_t *vm,struct cisco_card *card)
118 {
119 struct cisco_nio_binding *nb;
120
121 if (card && card->driver && card->drv_info)
122 for(nb=card->nio_list;nb;nb=nb->next)
123 card->driver->card_set_nio(vm,card,nb->port_id,nb->nio);
124 }
125
126 /* Disable all NIO for the specified card */
127 static inline
cisco_card_disable_all_nio(vm_instance_t * vm,struct cisco_card * card)128 void cisco_card_disable_all_nio(vm_instance_t *vm,struct cisco_card *card)
129 {
130 struct cisco_nio_binding *nb;
131
132 if (card && card->driver && card->drv_info)
133 for(nb=card->nio_list;nb;nb=nb->next)
134 card->driver->card_unset_nio(vm,card,nb->port_id);
135 }
136
137 /* Initialize a card */
138 static inline
cisco_card_init(vm_instance_t * vm,struct cisco_card * card,u_int id)139 int cisco_card_init(vm_instance_t *vm,struct cisco_card *card,u_int id)
140 {
141 size_t len;
142
143 /* Check that a device type is defined for this card */
144 if (!card || !card->dev_type || !card->driver)
145 return(-1);
146
147 /* Allocate device name */
148 len = strlen(card->dev_type) + 10;
149 if (!(card->dev_name = malloc(len))) {
150 vm_error(vm,"unable to allocate device name.\n");
151 return(-1);
152 }
153
154 snprintf(card->dev_name,len,"%s(%u)",card->dev_type,id);
155
156 /* Initialize card driver */
157 if (card->driver->card_init(vm,card) == -1) {
158 vm_error(vm,"unable to initialize card type '%s' (id %u)\n",
159 card->dev_type,id);
160 return(-1);
161 }
162
163 return(0);
164 }
165
166 /* Shutdown card */
cisco_card_shutdown(vm_instance_t * vm,struct cisco_card * card)167 static int cisco_card_shutdown(vm_instance_t *vm,struct cisco_card *card)
168 {
169 /* Check that a device type is defined for this card */
170 if (!card || !card->dev_type || !card->driver)
171 return(-1);
172
173 /* Shutdown the NM driver */
174 if (card->drv_info && (card->driver->card_shutdown(vm,card) == -1)) {
175 vm_error(vm,"unable to shutdown card type '%s' (slot %u/%u)\n",
176 card->dev_type,card->slot_id,card->subslot_id);
177 return(-1);
178 }
179
180 free(card->dev_name);
181 card->dev_name = NULL;
182 card->drv_info = NULL;
183 return(0);
184 }
185
186 /* Show info for the specified card */
cisco_card_show_info(vm_instance_t * vm,struct cisco_card * card)187 static int cisco_card_show_info(vm_instance_t *vm,struct cisco_card *card)
188 {
189 /* Check that a device type is defined for this card */
190 if (!card || !card->driver || !card->driver->card_show_info)
191 return(-1);
192
193 card->driver->card_show_info(vm,card);
194 return(0);
195 }
196
197 /* Save config for the specified card */
cisco_card_save_config(vm_instance_t * vm,struct cisco_card * card,FILE * fd)198 static int cisco_card_save_config(vm_instance_t *vm,struct cisco_card *card,
199 FILE *fd)
200 {
201 struct cisco_nio_binding *nb;
202
203 if (card != NULL) {
204 fprintf(fd,"vm add_slot_binding %s %u %u %s\n",
205 vm->name,card->slot_id,card->subslot_id,card->dev_type);
206
207 for(nb=card->nio_list;nb;nb=nb->next) {
208 fprintf(fd,"vm add_nio_binding %s %u %u %s\n",
209 vm->name,card->slot_id,nb->orig_port_id,nb->nio->name);
210 }
211 }
212
213 return(0);
214 }
215
216 /* Find a driver in a driver array */
217 static struct cisco_card_driver *
cisco_card_find_driver(struct cisco_card_driver ** array,char * dev_type)218 cisco_card_find_driver(struct cisco_card_driver **array,char *dev_type)
219 {
220 int i;
221
222 for(i=0;array[i]!=NULL;i++)
223 if (!strcmp(array[i]->dev_type,dev_type))
224 return array[i];
225
226 return NULL;
227 }
228
229 /* ======================================================================== */
230 /* High level routines for managing VM slots. */
231 /* ======================================================================== */
232
233 /* Get slot info */
vm_slot_get_card_ptr(vm_instance_t * vm,u_int slot_id)234 struct cisco_card *vm_slot_get_card_ptr(vm_instance_t *vm,u_int slot_id)
235 {
236 if (slot_id >= vm->nr_slots)
237 return NULL;
238
239 return(vm->slots[slot_id]);
240 }
241
242 /* Get info for a slot/port (with sub-cards) */
vm_slot_get_info(vm_instance_t * vm,u_int slot_id,u_int port_id,struct cisco_card *** rc,u_int * real_port_id)243 static int vm_slot_get_info(vm_instance_t *vm,u_int slot_id,u_int port_id,
244 struct cisco_card ***rc,u_int *real_port_id)
245 {
246 struct cisco_card *card;
247 u_int wic_id,card_type;
248
249 if (slot_id >= VM_MAX_SLOTS) {
250 *rc = NULL;
251 return(-1);
252 }
253
254 *rc = &vm->slots[slot_id];
255 card = vm->slots[slot_id];
256
257 card_type = (card != NULL) ? card->card_type : CISCO_CARD_TYPE_UNDEF;
258
259 switch(card_type) {
260 /*
261 * Handle WICs which are sub-slots for Network Modules (NM).
262 * Numbering: wic #0 => port_id = 0x10
263 * wic #1 => port_id = 0x20
264 */
265 case CISCO_CARD_TYPE_NM:
266 if (card->driver->wic_slots > 0) {
267 wic_id = port_id >> 4;
268
269 if (wic_id >= (CISCO_CARD_MAX_WIC+1)) {
270 vm_error(vm,"Invalid wic_id %u (slot %u)\n",wic_id,slot_id);
271 return(-1);
272 }
273
274 if (wic_id >= 0x01) {
275 /* wic card */
276 *rc = &card->sub_slots[wic_id - 1];
277 *real_port_id = port_id & 0x0F;
278 } else {
279 /* main card */
280 *real_port_id = port_id;
281 }
282 } else {
283 *real_port_id = port_id;
284 }
285 return(0);
286
287 /* No translation for Cisco 7200 Port Adapters and WICs */
288 case CISCO_CARD_TYPE_PA:
289 case CISCO_CARD_TYPE_WIC:
290 *real_port_id = port_id;
291 return(0);
292
293 /* Not initialized yet */
294 default:
295 *real_port_id = port_id;
296 return(0);
297 }
298 }
299
300 /* Translate a port ID (for sub-cards) */
301 static u_int
vm_slot_translate_port_id(vm_instance_t * vm,u_int slot_id,u_int port_id,struct cisco_card ** rc)302 vm_slot_translate_port_id(vm_instance_t *vm,u_int slot_id,u_int port_id,
303 struct cisco_card **rc)
304 {
305 struct cisco_card **tmp;
306 u_int real_port_id = 0;
307
308 vm_slot_get_info(vm,slot_id,port_id,&tmp,&real_port_id);
309 *rc = *tmp;
310 return(real_port_id);
311 }
312
313 /* Check if a slot has an active card */
vm_slot_active(vm_instance_t * vm,u_int slot_id,u_int port_id)314 int vm_slot_active(vm_instance_t *vm,u_int slot_id,u_int port_id)
315 {
316 struct cisco_card **rc;
317 u_int real_port_id;
318
319 if (vm_slot_get_info(vm,slot_id,port_id,&rc,&real_port_id) == -1)
320 return(FALSE);
321
322 if ((*rc == NULL) || ((*rc)->dev_type == NULL))
323 return(FALSE);
324
325 return(TRUE);
326 }
327
328 /* Set a flag for a card */
vm_slot_set_flag(vm_instance_t * vm,u_int slot_id,u_int port_id,u_int flag)329 int vm_slot_set_flag(vm_instance_t *vm,u_int slot_id,u_int port_id,u_int flag)
330 {
331 struct cisco_card **rc;
332 u_int real_port_id;
333
334 if (vm_slot_get_info(vm,slot_id,port_id,&rc,&real_port_id) == -1)
335 return(FALSE);
336
337 if (*rc == NULL)
338 return(FALSE);
339
340 (*rc)->card_flags |= flag;
341 return(TRUE);
342 }
343
344 /* Add a slot binding */
vm_slot_add_binding(vm_instance_t * vm,char * dev_type,u_int slot_id,u_int port_id)345 int vm_slot_add_binding(vm_instance_t *vm,char *dev_type,
346 u_int slot_id,u_int port_id)
347 {
348 struct cisco_card_driver *driver,**drv_array;
349 struct cisco_card **rc,*card,*nc,*parent;
350 u_int real_port_id,card_type,card_id;
351
352 if (vm_slot_get_info(vm,slot_id,port_id,&rc,&real_port_id) == -1)
353 return(-1);
354
355 /* check that this bay is empty */
356 if (*rc != NULL) {
357 if ((*rc)->card_flags & CISCO_CARD_FLAG_OVERRIDE) {
358 vm_slot_remove_binding(vm,slot_id,port_id);
359 } else {
360 vm_error(vm,"a card already exists in slot %u/%u (%s)\n",
361 slot_id,port_id,(*rc)->dev_type);
362 return(-1);
363 }
364 }
365
366 card = vm->slots[slot_id];
367
368 if (!card || (card == *rc)) {
369 /* Main slot */
370 drv_array = vm->slots_drivers;
371 card_type = vm->slots_type;
372 card_id = slot_id;
373 parent = NULL;
374 } else {
375 /* Subslot */
376 if (!card->driver->card_get_sub_info) {
377 vm_error(vm,"no sub-slot possible for slot %u/%u.\n",slot_id,port_id);
378 return(-1);
379 }
380
381 if (card->driver->card_get_sub_info(vm,card,port_id,
382 &drv_array,&card_type) == -1)
383 {
384 vm_error(vm,"no sub-slot info for slot %u/%u.\n",slot_id,port_id);
385 return(-1);
386 }
387
388 card_id = port_id;
389 parent = card;
390 }
391
392 assert(drv_array != NULL);
393
394 /* Find the card driver */
395 if (!(driver = cisco_card_find_driver(drv_array,dev_type))) {
396 vm_error(vm,"unknown card type '%s' for slot %u/%u.\n",
397 dev_type,slot_id,port_id);
398 return(-1);
399 }
400
401 /* Allocate new card info */
402 if (!(nc = cisco_card_create(card_type)))
403 return(-1);
404
405 nc->slot_id = slot_id;
406 nc->subslot_id = port_id;
407 nc->card_id = card_id;
408 nc->dev_type = driver->dev_type;
409 nc->driver = driver;
410 nc->parent = parent;
411 *rc = nc;
412 return(0);
413 }
414
415 /* Remove a slot binding */
vm_slot_remove_binding(vm_instance_t * vm,u_int slot_id,u_int port_id)416 int vm_slot_remove_binding(vm_instance_t *vm,u_int slot_id,u_int port_id)
417 {
418 struct cisco_card **rc,*sc;
419 u_int i,real_port_id;
420
421 if (vm_slot_get_info(vm,slot_id,port_id,&rc,&real_port_id) == -1)
422 return(-1);
423
424 if (*rc == NULL)
425 return(-1);
426
427 if ((*rc)->drv_info != NULL) {
428 vm_error(vm,"slot %u/%u is still active\n",slot_id,port_id);
429 return(-1);
430 }
431
432 for(i=0;i<CISCO_CARD_MAX_SUBSLOTS;i++) {
433 if ((sc = (*rc)->sub_slots[i]) != NULL) {
434 vm_error(vm,"sub-slot %u/%u is still active\n",
435 slot_id,sc->subslot_id);
436 return(-1);
437 }
438 }
439
440 /* Remove all NIOs bindings */
441 vm_slot_remove_all_nio_bindings(vm,slot_id);
442
443 /* Free the card info structure */
444 free(*rc);
445 *rc = NULL;
446 return(0);
447 }
448
449 /* Add a network IO binding */
vm_slot_add_nio_binding(vm_instance_t * vm,u_int slot_id,u_int port_id,char * nio_name)450 int vm_slot_add_nio_binding(vm_instance_t *vm,u_int slot_id,u_int port_id,
451 char *nio_name)
452 {
453 struct cisco_nio_binding *nb;
454 struct cisco_card *card,*rc;
455 u_int real_port_id;
456 netio_desc_t *nio;
457
458 if (!(card = vm_slot_get_card_ptr(vm,slot_id)))
459 return(-1);
460
461 /* Get the real card (in case this is a sub-slot) */
462 real_port_id = vm_slot_translate_port_id(vm,slot_id,port_id,&rc);
463
464 if (rc == NULL)
465 return(-1);
466
467 /* check that a NIO is not already bound to this port */
468 if (cisco_card_find_nio_binding(rc,real_port_id) != NULL) {
469 vm_error(vm,"a NIO already exists for interface %u/%u.\n",
470 slot_id,port_id);
471 return(-1);
472 }
473
474 /* acquire a reference on the NIO object */
475 if (!(nio = netio_acquire(nio_name))) {
476 vm_error(vm,"unable to find NIO '%s'.\n",nio_name);
477 return(-1);
478 }
479
480 /* create a new binding */
481 if (!(nb = malloc(sizeof(*nb)))) {
482 vm_error(vm,"unable to create NIO binding for interface %u/%u.\n",
483 slot_id,port_id);
484 netio_release(nio_name);
485 return(-1);
486 }
487
488 memset(nb,0,sizeof(*nb));
489 nb->nio = nio;
490 nb->port_id = real_port_id;
491 nb->orig_port_id = port_id;
492
493 nb->next = rc->nio_list;
494 if (nb->next) nb->next->prev = nb;
495 rc->nio_list = nb;
496 return(0);
497 }
498
499 /* Remove a NIO binding */
vm_slot_remove_nio_binding(vm_instance_t * vm,u_int slot_id,u_int port_id)500 int vm_slot_remove_nio_binding(vm_instance_t *vm,u_int slot_id,u_int port_id)
501 {
502 struct cisco_nio_binding *nb;
503 struct cisco_card *card,*rc;
504 u_int real_port_id;
505
506 if (!(card = vm_slot_get_card_ptr(vm,slot_id)))
507 return(-1);
508
509 /* Get the real card (in case this is a sub-slot) */
510 real_port_id = vm_slot_translate_port_id(vm,slot_id,port_id,&rc);
511
512 if (rc == NULL)
513 return(-1);
514
515 /* no nio binding for this slot/port ? */
516 if (!(nb = cisco_card_find_nio_binding(rc,real_port_id)))
517 return(-1);
518
519 /* tell the NM driver to stop using this NIO */
520 if (rc->driver)
521 rc->driver->card_unset_nio(vm,rc,port_id);
522
523 /* remove this entry from the double linked list */
524 if (nb->next)
525 nb->next->prev = nb->prev;
526
527 if (nb->prev) {
528 nb->prev->next = nb->next;
529 } else {
530 rc->nio_list = nb->next;
531 }
532
533 /* unreference NIO object */
534 netio_release(nb->nio->name);
535 free(nb);
536 return(0);
537 }
538
539 /* Remove all NIO bindings for the specified slot (sub-slots included) */
vm_slot_remove_all_nio_bindings(vm_instance_t * vm,u_int slot_id)540 int vm_slot_remove_all_nio_bindings(vm_instance_t *vm,u_int slot_id)
541 {
542 struct cisco_card *card,*sc;
543 int i;
544
545 if (!(card = vm_slot_get_card_ptr(vm,slot_id)))
546 return(-1);
547
548 /* Remove NIO bindings for the main slot */
549 cisco_card_remove_all_nio_bindings(vm,card);
550
551 /* Remove NIO bindings for all sub-slots */
552 for(i=0;i<CISCO_CARD_MAX_SUBSLOTS;i++) {
553 if ((sc = card->sub_slots[i]) != NULL)
554 cisco_card_remove_all_nio_bindings(vm,sc);
555 }
556
557 return(0);
558 }
559
560 /* Enable a Network IO descriptor for the specified slot */
vm_slot_enable_nio(vm_instance_t * vm,u_int slot_id,u_int port_id)561 int vm_slot_enable_nio(vm_instance_t *vm,u_int slot_id,u_int port_id)
562 {
563 struct cisco_nio_binding *nb;
564 struct cisco_card *card,*rc;
565 u_int real_port_id;
566
567 if (!(card = vm_slot_get_card_ptr(vm,slot_id)))
568 return(-1);
569
570 /* Get the real card (in case this is a sub-slot) */
571 real_port_id = vm_slot_translate_port_id(vm,slot_id,port_id,&rc);
572
573 if (rc == NULL)
574 return(-1);
575
576 /* no nio binding for this slot/port ? */
577 if (!(nb = cisco_card_find_nio_binding(rc,real_port_id)))
578 return(-1);
579
580 /* check that the driver is defined and successfully initialized */
581 if (!rc->driver || !rc->drv_info)
582 return(-1);
583
584 return(rc->driver->card_set_nio(vm,rc,real_port_id,nb->nio));
585 }
586
587 /* Disable Network IO descriptor for the specified slot */
vm_slot_disable_nio(vm_instance_t * vm,u_int slot_id,u_int port_id)588 int vm_slot_disable_nio(vm_instance_t *vm,u_int slot_id,u_int port_id)
589 {
590 struct cisco_nio_binding *nb;
591 struct cisco_card *card,*rc;
592 u_int real_port_id;
593
594 if (!(card = vm_slot_get_card_ptr(vm,slot_id)))
595 return(-1);
596
597 /* Get the real card (in case this is a sub-slot) */
598 real_port_id = vm_slot_translate_port_id(vm,slot_id,port_id,&rc);
599
600 if (rc == NULL)
601 return(-1);
602
603 /* no nio binding for this slot/port ? */
604 if (!(nb = cisco_card_find_nio_binding(rc,real_port_id)))
605 return(-1);
606
607 /* check that the driver is defined and successfully initialized */
608 if (!rc->driver || !rc->drv_info)
609 return(-1);
610
611 return(rc->driver->card_unset_nio(vm,rc,real_port_id));
612 }
613
614 /* Enable all NIO for the specified slot (sub-slots included) */
vm_slot_enable_all_nio(vm_instance_t * vm,u_int slot_id)615 int vm_slot_enable_all_nio(vm_instance_t *vm,u_int slot_id)
616 {
617 struct cisco_card *card;
618 int i;
619
620 if (!(card = vm_slot_get_card_ptr(vm,slot_id)))
621 return(-1);
622
623 /* Enable slot NIOs */
624 cisco_card_enable_all_nio(vm,card);
625
626 /* Enable NIO of sub-slots */
627 for(i=0;i<CISCO_CARD_MAX_SUBSLOTS;i++)
628 cisco_card_enable_all_nio(vm,card->sub_slots[i]);
629
630 return(0);
631 }
632
633 /* Disable all NIO for the specified slot (sub-slots included) */
vm_slot_disable_all_nio(vm_instance_t * vm,u_int slot_id)634 int vm_slot_disable_all_nio(vm_instance_t *vm,u_int slot_id)
635 {
636 struct cisco_card *card;
637 int i;
638
639 if (!(card = vm_slot_get_card_ptr(vm,slot_id)))
640 return(-1);
641
642 /* Disable slot NIOs */
643 cisco_card_disable_all_nio(vm,card);
644
645 /* Disable NIO of sub-slots */
646 for(i=0;i<CISCO_CARD_MAX_SUBSLOTS;i++)
647 cisco_card_disable_all_nio(vm,card->sub_slots[i]);
648
649 return(0);
650 }
651
652 /* Initialize the specified slot (sub-slots included) */
vm_slot_init(vm_instance_t * vm,u_int slot_id)653 int vm_slot_init(vm_instance_t *vm,u_int slot_id)
654 {
655 struct cisco_card *card;
656 int i;
657
658 if (!(card = vm_slot_get_card_ptr(vm,slot_id)))
659 return(0);
660
661 /* Initialize card main module */
662 cisco_card_init(vm,card,slot_id);
663
664 /* Initialize sub-slots */
665 for(i=0;i<CISCO_CARD_MAX_SUBSLOTS;i++)
666 cisco_card_init(vm,card->sub_slots[i],slot_id);
667
668 /* Enable all NIO */
669 vm_slot_enable_all_nio(vm,slot_id);
670 return(0);
671 }
672
673 /* Initialize all slots of a VM */
vm_slot_init_all(vm_instance_t * vm)674 int vm_slot_init_all(vm_instance_t *vm)
675 {
676 int i;
677
678 for(i=0;i<vm->nr_slots;i++) {
679 if (vm_slot_init(vm,i) == -1) {
680 vm_error(vm,"unable to initialize slot %u\n",i);
681 return(-1);
682 }
683 }
684
685 return(0);
686 }
687
688 /* Shutdown the specified slot (sub-slots included) */
vm_slot_shutdown(vm_instance_t * vm,u_int slot_id)689 int vm_slot_shutdown(vm_instance_t *vm,u_int slot_id)
690 {
691 struct cisco_card *card;
692 int i;
693
694 if (!(card = vm_slot_get_card_ptr(vm,slot_id)))
695 return(-1);
696
697 /* Disable all NIO */
698 vm_slot_disable_all_nio(vm,slot_id);
699
700 /* Shutdown sub-slots */
701 for(i=0;i<CISCO_CARD_MAX_SUBSLOTS;i++)
702 cisco_card_shutdown(vm,card->sub_slots[i]);
703
704 /* Shutdown card main module */
705 cisco_card_shutdown(vm,card);
706 return(0);
707 }
708
709 /* Shutdown all slots of a VM */
vm_slot_shutdown_all(vm_instance_t * vm)710 int vm_slot_shutdown_all(vm_instance_t *vm)
711 {
712 int i;
713
714 for(i=0;i<vm->nr_slots;i++)
715 vm_slot_shutdown(vm,i);
716
717 return(0);
718 }
719
720 /* Show info about the specified slot (sub-slots included) */
vm_slot_show_info(vm_instance_t * vm,u_int slot_id)721 int vm_slot_show_info(vm_instance_t *vm,u_int slot_id)
722 {
723 struct cisco_card *card;
724
725 if (!(card = vm_slot_get_card_ptr(vm,slot_id)))
726 return(-1);
727
728 cisco_card_show_info(vm,card);
729 return(0);
730 }
731
732 /* Show info about all slots */
vm_slot_show_all_info(vm_instance_t * vm)733 int vm_slot_show_all_info(vm_instance_t *vm)
734 {
735 int i;
736
737 for(i=0;i<vm->nr_slots;i++)
738 vm_slot_show_info(vm,i);
739
740 return(0);
741 }
742
743 /* Check if the specified slot has a valid EEPROM defined */
vm_slot_check_eeprom(vm_instance_t * vm,u_int slot_id,u_int port_id)744 int vm_slot_check_eeprom(vm_instance_t *vm,u_int slot_id,u_int port_id)
745 {
746 struct cisco_card *card,*rc;
747
748 if (!(card = vm_slot_get_card_ptr(vm,slot_id)))
749 return(FALSE);
750
751 /* Get the real card (in case this is a sub-slot) */
752 vm_slot_translate_port_id(vm,slot_id,port_id,&rc);
753
754 if (rc == NULL)
755 return(FALSE);
756
757 return(cisco_card_check_eeprom(rc));
758 }
759
760 /* Returns the EEPROM data of the specified slot */
761 struct cisco_eeprom *
vm_slot_get_eeprom(vm_instance_t * vm,u_int slot_id,u_int port_id)762 vm_slot_get_eeprom(vm_instance_t *vm,u_int slot_id,u_int port_id)
763 {
764 struct cisco_card *card,*rc;
765
766 if (!(card = vm_slot_get_card_ptr(vm,slot_id)))
767 return NULL;
768
769 /* Get the real card (in case this is a sub-slot) */
770 vm_slot_translate_port_id(vm,slot_id,port_id,&rc);
771
772 if (rc == NULL)
773 return NULL;
774
775 return(&rc->eeprom);
776 }
777
778 /* Save config for the specified slot (sub-slots included) */
vm_slot_save_config(vm_instance_t * vm,u_int slot_id,FILE * fd)779 int vm_slot_save_config(vm_instance_t *vm,u_int slot_id,FILE *fd)
780 {
781 struct cisco_card *card;
782 int i;
783
784 if (!(card = vm_slot_get_card_ptr(vm,slot_id)))
785 return(-1);
786
787 /* Main slot info */
788 cisco_card_save_config(vm,card,fd);
789
790 /* Shutdown sub-slots */
791 for(i=0;i<CISCO_CARD_MAX_SUBSLOTS;i++)
792 cisco_card_save_config(vm,card->sub_slots[i],fd);
793
794 return(0);
795 }
796
797 /* Save config for all slots */
vm_slot_save_all_config(vm_instance_t * vm,FILE * fd)798 int vm_slot_save_all_config(vm_instance_t *vm,FILE *fd)
799 {
800 int i;
801
802 for(i=0;i<vm->nr_slots;i++)
803 vm_slot_save_config(vm,i,fd);
804
805 return(0);
806 }
807
808 /* Show slot drivers */
vm_slot_show_drivers(vm_instance_t * vm)809 int vm_slot_show_drivers(vm_instance_t *vm)
810 {
811 char *slot_type;
812 int i;
813
814 if (!vm->slots_drivers)
815 return(-1);
816
817 slot_type = cisco_card_get_type_desc(vm->slots_type);
818
819 printf("Available %s %s drivers:\n",vm->platform->log_name,slot_type);
820
821 for(i=0;vm->slots_drivers[i];i++) {
822 printf(" * %s %s\n",
823 vm->slots_drivers[i]->dev_type,
824 !vm->slots_drivers[i]->supported ? "(NOT WORKING)" : "");
825 }
826
827 printf("\n");
828 return(0);
829 }
830
831 /* Maximum number of tokens in a slot description */
832 #define SLOT_DESC_MAX_TOKENS 8
833
834 /* Create a Network Module (command line) */
vm_slot_cmd_create(vm_instance_t * vm,char * str)835 int vm_slot_cmd_create(vm_instance_t *vm,char *str)
836 {
837 char *tokens[SLOT_DESC_MAX_TOKENS];
838 int i,count,res;
839 u_int slot_id,port_id;
840
841 /* A port adapter description is like "1:0:NM-1FE" */
842 count = m_strsplit(str,':',tokens,SLOT_DESC_MAX_TOKENS);
843
844 if ((count < 2) || (count > 3)) {
845 vm_error(vm,"unable to parse slot description '%s'.\n",str);
846 return(-1);
847 }
848
849 /* Parse the slot id */
850 slot_id = atoi(tokens[0]);
851
852 /* Parse the sub-slot id */
853 if (count == 3)
854 port_id = atoi(tokens[1]);
855 else
856 port_id = 0;
857
858 /* Add this new slot to the current slot list */
859 res = vm_slot_add_binding(vm,tokens[count-1],slot_id,port_id);
860
861 /* The complete array was cleaned by strsplit */
862 for(i=0;i<SLOT_DESC_MAX_TOKENS;i++)
863 free(tokens[i]);
864
865 return(res);
866 }
867
868 /* Add a Network IO descriptor binding (command line) */
vm_slot_cmd_add_nio(vm_instance_t * vm,char * str)869 int vm_slot_cmd_add_nio(vm_instance_t *vm,char *str)
870 {
871 char *tokens[SLOT_DESC_MAX_TOKENS];
872 int i,count,nio_type,res=-1;
873 u_int slot_id,port_id;
874 netio_desc_t *nio;
875 char nio_name[128];
876
877 /* A NIO binding description is like "1:3:tap:tap0" */
878 if ((count = m_strsplit(str,':',tokens,SLOT_DESC_MAX_TOKENS)) < 3) {
879 vm_error(vm,"unable to parse NIO description '%s'.\n",str);
880 return(-1);
881 }
882
883 /* Parse the slot id */
884 slot_id = atoi(tokens[0]);
885
886 /* Parse the port id */
887 port_id = atoi(tokens[1]);
888
889 /* Autogenerate a NIO name */
890 snprintf(nio_name,sizeof(nio_name),"%s-i%u/%u/%u",
891 vm_get_type(vm),vm->instance_id,slot_id,port_id);
892
893 /* Create the Network IO descriptor */
894 nio = NULL;
895 nio_type = netio_get_type(tokens[2]);
896
897 switch(nio_type) {
898 case NETIO_TYPE_UNIX:
899 if (count != 5) {
900 vm_error(vm,"invalid number of arguments for UNIX NIO '%s'\n",str);
901 goto done;
902 }
903
904 nio = netio_desc_create_unix(nio_name,tokens[3],tokens[4]);
905 break;
906
907 case NETIO_TYPE_VDE:
908 if (count != 5) {
909 vm_error(vm,"invalid number of arguments for VDE NIO '%s'\n",str);
910 goto done;
911 }
912
913 nio = netio_desc_create_vde(nio_name,tokens[3],tokens[4]);
914 break;
915
916 case NETIO_TYPE_TAP:
917 if (count != 4) {
918 vm_error(vm,"invalid number of arguments for TAP NIO '%s'\n",str);
919 goto done;
920 }
921
922 nio = netio_desc_create_tap(nio_name,tokens[3]);
923 break;
924
925 case NETIO_TYPE_UDP:
926 if (count != 6) {
927 vm_error(vm,"invalid number of arguments for UDP NIO '%s'\n",str);
928 goto done;
929 }
930
931 nio = netio_desc_create_udp(nio_name,atoi(tokens[3]),
932 tokens[4],atoi(tokens[5]));
933 break;
934
935 case NETIO_TYPE_TCP_CLI:
936 if (count != 5) {
937 vm_error(vm,"invalid number of arguments for TCP CLI NIO '%s'\n",
938 str);
939 goto done;
940 }
941
942 nio = netio_desc_create_tcp_cli(nio_name,tokens[3],tokens[4]);
943 break;
944
945 case NETIO_TYPE_TCP_SER:
946 if (count != 4) {
947 vm_error(vm,"invalid number of arguments for TCP SER NIO '%s'\n",
948 str);
949 goto done;
950 }
951
952 nio = netio_desc_create_tcp_ser(nio_name,tokens[3]);
953 break;
954
955 case NETIO_TYPE_NULL:
956 nio = netio_desc_create_null(nio_name);
957 break;
958
959 #ifdef LINUX_ETH
960 case NETIO_TYPE_LINUX_ETH:
961 if (count != 4) {
962 vm_error(vm,"invalid number of arguments for Linux Eth NIO '%s'\n",
963 str);
964 goto done;
965 }
966
967 nio = netio_desc_create_lnxeth(nio_name,tokens[3]);
968 break;
969 #endif
970
971 #ifdef GEN_ETH
972 case NETIO_TYPE_GEN_ETH:
973 if (count != 4) {
974 vm_error(vm,
975 "invalid number of arguments for Generic Eth NIO '%s'\n",
976 str);
977 goto done;
978 }
979
980 nio = netio_desc_create_geneth(nio_name,tokens[3]);
981 break;
982 #endif
983
984 default:
985 vm_error(vm,"unknown NETIO type '%s'\n",tokens[2]);
986 goto done;
987 }
988
989 if (!nio) {
990 vm_error(vm,"unable to create NETIO descriptor for slot %u\n",slot_id);
991 goto done;
992 }
993
994 if (vm_slot_add_nio_binding(vm,slot_id,port_id,nio_name) == -1) {
995 vm_error(vm,"unable to add NETIO binding for slot %u\n",slot_id);
996 netio_release(nio_name);
997 netio_delete(nio_name);
998 goto done;
999 }
1000
1001 netio_release(nio_name);
1002 res = 0;
1003
1004 done:
1005 /* The complete array was cleaned by strsplit */
1006 for(i=0;i<SLOT_DESC_MAX_TOKENS;i++)
1007 free(tokens[i]);
1008
1009 return(res);
1010 }
1011