Commit 7c9d8e07e188597e570a311efc46cb1ab013e5e7
1 parent
868bfe2b
new network emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1622 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
7 changed files
with
902 additions
and
419 deletions
gdbstub.c
| ... | ... | @@ -704,19 +704,19 @@ void gdb_exit(CPUState *env, int code) |
| 704 | 704 | } |
| 705 | 705 | |
| 706 | 706 | #else |
| 707 | -static int gdb_can_read(void *opaque) | |
| 708 | -{ | |
| 709 | - return 256; | |
| 710 | -} | |
| 711 | - | |
| 712 | -static void gdb_read(void *opaque, const uint8_t *buf, int size) | |
| 707 | +static void gdb_read(void *opaque) | |
| 713 | 708 | { |
| 714 | 709 | GDBState *s = opaque; |
| 715 | - int i; | |
| 710 | + int i, size; | |
| 711 | + uint8_t buf[4096]; | |
| 712 | + | |
| 713 | + size = read(s->fd, buf, sizeof(buf)); | |
| 714 | + if (size < 0) | |
| 715 | + return; | |
| 716 | 716 | if (size == 0) { |
| 717 | 717 | /* end of connection */ |
| 718 | 718 | qemu_del_vm_stop_handler(gdb_vm_stopped, s); |
| 719 | - qemu_del_fd_read_handler(s->fd); | |
| 719 | + qemu_set_fd_handler(s->fd, NULL, NULL, NULL); | |
| 720 | 720 | qemu_free(s); |
| 721 | 721 | vm_start(); |
| 722 | 722 | } else { |
| ... | ... | @@ -727,7 +727,7 @@ static void gdb_read(void *opaque, const uint8_t *buf, int size) |
| 727 | 727 | |
| 728 | 728 | #endif |
| 729 | 729 | |
| 730 | -static void gdb_accept(void *opaque, const uint8_t *buf, int size) | |
| 730 | +static void gdb_accept(void *opaque) | |
| 731 | 731 | { |
| 732 | 732 | GDBState *s; |
| 733 | 733 | struct sockaddr_in sockaddr; |
| ... | ... | @@ -768,7 +768,7 @@ static void gdb_accept(void *opaque, const uint8_t *buf, int size) |
| 768 | 768 | vm_stop(EXCP_INTERRUPT); |
| 769 | 769 | |
| 770 | 770 | /* start handling I/O */ |
| 771 | - qemu_add_fd_read_handler(s->fd, gdb_can_read, gdb_read, s); | |
| 771 | + qemu_set_fd_handler(s->fd, gdb_read, NULL, s); | |
| 772 | 772 | /* when the VM is stopped, the following callback is called */ |
| 773 | 773 | qemu_add_vm_stop_handler(gdb_vm_stopped, s); |
| 774 | 774 | #endif |
| ... | ... | @@ -815,9 +815,9 @@ int gdbserver_start(int port) |
| 815 | 815 | return -1; |
| 816 | 816 | /* accept connections */ |
| 817 | 817 | #ifdef CONFIG_USER_ONLY |
| 818 | - gdb_accept (NULL, NULL, 0); | |
| 818 | + gdb_accept (NULL); | |
| 819 | 819 | #else |
| 820 | - qemu_add_fd_read_handler(gdbserver_fd, NULL, gdb_accept, NULL); | |
| 820 | + qemu_set_fd_handler(gdbserver_fd, gdb_accept, NULL, NULL); | |
| 821 | 821 | #endif |
| 822 | 822 | return 0; |
| 823 | 823 | } | ... | ... |
hw/lance.c
| ... | ... | @@ -154,7 +154,8 @@ struct lance_init_block { |
| 154 | 154 | #define LEDMA_MAXADDR (LEDMA_REGS * 4 - 1) |
| 155 | 155 | |
| 156 | 156 | typedef struct LANCEState { |
| 157 | - NetDriverState *nd; | |
| 157 | + VLANClientState *vc; | |
| 158 | + uint8_t macaddr[6]; /* init mac address */ | |
| 158 | 159 | uint32_t leptr; |
| 159 | 160 | uint16_t addr; |
| 160 | 161 | uint16_t regs[LE_NREGS]; |
| ... | ... | @@ -169,7 +170,7 @@ static void lance_send(void *opaque); |
| 169 | 170 | static void lance_reset(void *opaque) |
| 170 | 171 | { |
| 171 | 172 | LANCEState *s = opaque; |
| 172 | - memcpy(s->phys, s->nd->macaddr, 6); | |
| 173 | + memcpy(s->phys, s->macaddr, 6); | |
| 173 | 174 | s->rxptr = 0; |
| 174 | 175 | s->txptr = 0; |
| 175 | 176 | memset(s->regs, 0, LE_NREGS * 2); |
| ... | ... | @@ -280,31 +281,6 @@ static CPUWriteMemoryFunc *lance_mem_write[3] = { |
| 280 | 281 | }; |
| 281 | 282 | |
| 282 | 283 | |
| 283 | -/* return the max buffer size if the LANCE can receive more data */ | |
| 284 | -static int lance_can_receive(void *opaque) | |
| 285 | -{ | |
| 286 | - LANCEState *s = opaque; | |
| 287 | - uint32_t dmaptr = s->leptr + s->ledmaregs[3]; | |
| 288 | - struct lance_init_block *ib; | |
| 289 | - int i; | |
| 290 | - uint8_t temp8; | |
| 291 | - | |
| 292 | - if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP) | |
| 293 | - return 0; | |
| 294 | - | |
| 295 | - ib = (void *) iommu_translate(dmaptr); | |
| 296 | - | |
| 297 | - for (i = 0; i < RX_RING_SIZE; i++) { | |
| 298 | - cpu_physical_memory_read((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp8, 1); | |
| 299 | - if (temp8 == (LE_R1_OWN)) { | |
| 300 | - DPRINTF("can receive %d\n", RX_BUFF_SIZE); | |
| 301 | - return RX_BUFF_SIZE; | |
| 302 | - } | |
| 303 | - } | |
| 304 | - DPRINTF("cannot receive\n"); | |
| 305 | - return 0; | |
| 306 | -} | |
| 307 | - | |
| 308 | 284 | #define MIN_BUF_SIZE 60 |
| 309 | 285 | |
| 310 | 286 | static void lance_receive(void *opaque, const uint8_t *buf, int size) |
| ... | ... | @@ -368,7 +344,7 @@ static void lance_send(void *opaque) |
| 368 | 344 | temp16 = (~temp16) + 1; |
| 369 | 345 | cpu_physical_memory_read((uint32_t)&ib->tx_buf[i], pkt_buf, temp16); |
| 370 | 346 | DPRINTF("sending packet, len %d\n", temp16); |
| 371 | - qemu_send_packet(s->nd, pkt_buf, temp16); | |
| 347 | + qemu_send_packet(s->vc, pkt_buf, temp16); | |
| 372 | 348 | temp8 = LE_T1_POK; |
| 373 | 349 | cpu_physical_memory_write((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp8, 1); |
| 374 | 350 | s->txptr = (s->txptr + 1) & TX_RING_MOD_MASK; |
| ... | ... | @@ -443,7 +419,7 @@ static int lance_load(QEMUFile *f, void *opaque, int version_id) |
| 443 | 419 | return 0; |
| 444 | 420 | } |
| 445 | 421 | |
| 446 | -void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr) | |
| 422 | +void lance_init(NICInfo *nd, int irq, uint32_t leaddr, uint32_t ledaddr) | |
| 447 | 423 | { |
| 448 | 424 | LANCEState *s; |
| 449 | 425 | int lance_io_memory, ledma_io_memory; |
| ... | ... | @@ -452,7 +428,6 @@ void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr) |
| 452 | 428 | if (!s) |
| 453 | 429 | return; |
| 454 | 430 | |
| 455 | - s->nd = nd; | |
| 456 | 431 | s->irq = irq; |
| 457 | 432 | |
| 458 | 433 | lance_io_memory = cpu_register_io_memory(0, lance_mem_read, lance_mem_write, s); |
| ... | ... | @@ -461,8 +436,21 @@ void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr) |
| 461 | 436 | ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, s); |
| 462 | 437 | cpu_register_physical_memory(ledaddr, 16, ledma_io_memory); |
| 463 | 438 | |
| 439 | + memcpy(s->macaddr, nd->macaddr, 6); | |
| 440 | + | |
| 464 | 441 | lance_reset(s); |
| 465 | - qemu_add_read_packet(nd, lance_can_receive, lance_receive, s); | |
| 442 | + | |
| 443 | + s->vc = qemu_new_vlan_client(nd->vlan, lance_receive, s); | |
| 444 | + | |
| 445 | + snprintf(s->vc->info_str, sizeof(s->vc->info_str), | |
| 446 | + "lance macaddr=%02x:%02x:%02x:%02x:%02x:%02x", | |
| 447 | + s->macaddr[0], | |
| 448 | + s->macaddr[1], | |
| 449 | + s->macaddr[2], | |
| 450 | + s->macaddr[3], | |
| 451 | + s->macaddr[4], | |
| 452 | + s->macaddr[5]); | |
| 453 | + | |
| 466 | 454 | register_savevm("lance", leaddr, 1, lance_save, lance_load, s); |
| 467 | 455 | qemu_register_reset(lance_reset, s); |
| 468 | 456 | } | ... | ... |
hw/ne2000.c
| ... | ... | @@ -122,6 +122,7 @@ typedef struct NE2000State { |
| 122 | 122 | uint16_t rcnt; |
| 123 | 123 | uint32_t rsar; |
| 124 | 124 | uint8_t rsr; |
| 125 | + uint8_t rxcr; | |
| 125 | 126 | uint8_t isr; |
| 126 | 127 | uint8_t dcfg; |
| 127 | 128 | uint8_t imr; |
| ... | ... | @@ -130,7 +131,8 @@ typedef struct NE2000State { |
| 130 | 131 | uint8_t mult[8]; /* multicast mask array */ |
| 131 | 132 | int irq; |
| 132 | 133 | PCIDevice *pci_dev; |
| 133 | - NetDriverState *nd; | |
| 134 | + VLANClientState *vc; | |
| 135 | + uint8_t macaddr[6]; | |
| 134 | 136 | uint8_t mem[NE2000_MEM_SIZE]; |
| 135 | 137 | } NE2000State; |
| 136 | 138 | |
| ... | ... | @@ -139,7 +141,7 @@ static void ne2000_reset(NE2000State *s) |
| 139 | 141 | int i; |
| 140 | 142 | |
| 141 | 143 | s->isr = ENISR_RESET; |
| 142 | - memcpy(s->mem, s->nd->macaddr, 6); | |
| 144 | + memcpy(s->mem, s->macaddr, 6); | |
| 143 | 145 | s->mem[14] = 0x57; |
| 144 | 146 | s->mem[15] = 0x57; |
| 145 | 147 | |
| ... | ... | @@ -167,6 +169,30 @@ static void ne2000_update_irq(NE2000State *s) |
| 167 | 169 | } |
| 168 | 170 | } |
| 169 | 171 | |
| 172 | +#define POLYNOMIAL 0x04c11db6 | |
| 173 | + | |
| 174 | +/* From FreeBSD */ | |
| 175 | +/* XXX: optimize */ | |
| 176 | +static int compute_mcast_idx(const uint8_t *ep) | |
| 177 | +{ | |
| 178 | + uint32_t crc; | |
| 179 | + int carry, i, j; | |
| 180 | + uint8_t b; | |
| 181 | + | |
| 182 | + crc = 0xffffffff; | |
| 183 | + for (i = 0; i < 6; i++) { | |
| 184 | + b = *ep++; | |
| 185 | + for (j = 0; j < 8; j++) { | |
| 186 | + carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01); | |
| 187 | + crc <<= 1; | |
| 188 | + b >>= 1; | |
| 189 | + if (carry) | |
| 190 | + crc = ((crc ^ POLYNOMIAL) | carry); | |
| 191 | + } | |
| 192 | + } | |
| 193 | + return (crc >> 26); | |
| 194 | +} | |
| 195 | + | |
| 170 | 196 | /* return the max buffer size if the NE2000 can receive more data */ |
| 171 | 197 | static int ne2000_can_receive(void *opaque) |
| 172 | 198 | { |
| ... | ... | @@ -192,13 +218,46 @@ static void ne2000_receive(void *opaque, const uint8_t *buf, int size) |
| 192 | 218 | { |
| 193 | 219 | NE2000State *s = opaque; |
| 194 | 220 | uint8_t *p; |
| 195 | - int total_len, next, avail, len, index; | |
| 221 | + int total_len, next, avail, len, index, mcast_idx; | |
| 196 | 222 | uint8_t buf1[60]; |
| 223 | + static const uint8_t broadcast_macaddr[6] = | |
| 224 | + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | |
| 197 | 225 | |
| 198 | 226 | #if defined(DEBUG_NE2000) |
| 199 | 227 | printf("NE2000: received len=%d\n", size); |
| 200 | 228 | #endif |
| 201 | 229 | |
| 230 | + if (!ne2000_can_receive(s)) | |
| 231 | + return; | |
| 232 | + | |
| 233 | + /* XXX: check this */ | |
| 234 | + if (s->rxcr & 0x10) { | |
| 235 | + /* promiscuous: receive all */ | |
| 236 | + } else { | |
| 237 | + if (!memcmp(buf, broadcast_macaddr, 6)) { | |
| 238 | + /* broadcast address */ | |
| 239 | + if (!(s->rxcr & 0x04)) | |
| 240 | + return; | |
| 241 | + } else if (buf[0] & 0x01) { | |
| 242 | + /* multicast */ | |
| 243 | + if (!(s->rxcr & 0x08)) | |
| 244 | + return; | |
| 245 | + mcast_idx = compute_mcast_idx(buf); | |
| 246 | + if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7)))) | |
| 247 | + return; | |
| 248 | + } else if (s->mem[0] == buf[0] && | |
| 249 | + s->mem[2] == buf[1] && | |
| 250 | + s->mem[4] == buf[2] && | |
| 251 | + s->mem[6] == buf[3] && | |
| 252 | + s->mem[8] == buf[4] && | |
| 253 | + s->mem[10] == buf[5]) { | |
| 254 | + /* match */ | |
| 255 | + } else { | |
| 256 | + return; | |
| 257 | + } | |
| 258 | + } | |
| 259 | + | |
| 260 | + | |
| 202 | 261 | /* if too small buffer, then expand it */ |
| 203 | 262 | if (size < MIN_BUF_SIZE) { |
| 204 | 263 | memcpy(buf1, buf, size); |
| ... | ... | @@ -273,7 +332,7 @@ static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val) |
| 273 | 332 | index -= NE2000_PMEM_SIZE; |
| 274 | 333 | /* fail safe: check range on the transmitted length */ |
| 275 | 334 | if (index + s->tcnt <= NE2000_PMEM_END) { |
| 276 | - qemu_send_packet(s->nd, s->mem + index, s->tcnt); | |
| 335 | + qemu_send_packet(s->vc, s->mem + index, s->tcnt); | |
| 277 | 336 | } |
| 278 | 337 | /* signal end of transfert */ |
| 279 | 338 | s->tsr = ENTSR_PTX; |
| ... | ... | @@ -320,6 +379,9 @@ static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val) |
| 320 | 379 | case EN0_RCNTHI: |
| 321 | 380 | s->rcnt = (s->rcnt & 0x00ff) | (val << 8); |
| 322 | 381 | break; |
| 382 | + case EN0_RXCR: | |
| 383 | + s->rxcr = val; | |
| 384 | + break; | |
| 323 | 385 | case EN0_DCFG: |
| 324 | 386 | s->dcfg = val; |
| 325 | 387 | break; |
| ... | ... | @@ -608,10 +670,10 @@ static int ne2000_load(QEMUFile* f,void* opaque,int version_id) |
| 608 | 670 | return 0; |
| 609 | 671 | } |
| 610 | 672 | |
| 611 | -void isa_ne2000_init(int base, int irq, NetDriverState *nd) | |
| 673 | +void isa_ne2000_init(int base, int irq, NICInfo *nd) | |
| 612 | 674 | { |
| 613 | 675 | NE2000State *s; |
| 614 | - | |
| 676 | + | |
| 615 | 677 | s = qemu_mallocz(sizeof(NE2000State)); |
| 616 | 678 | if (!s) |
| 617 | 679 | return; |
| ... | ... | @@ -627,14 +689,22 @@ void isa_ne2000_init(int base, int irq, NetDriverState *nd) |
| 627 | 689 | register_ioport_write(base + 0x1f, 1, 1, ne2000_reset_ioport_write, s); |
| 628 | 690 | register_ioport_read(base + 0x1f, 1, 1, ne2000_reset_ioport_read, s); |
| 629 | 691 | s->irq = irq; |
| 630 | - s->nd = nd; | |
| 692 | + memcpy(s->macaddr, nd->macaddr, 6); | |
| 631 | 693 | |
| 632 | 694 | ne2000_reset(s); |
| 633 | 695 | |
| 634 | - qemu_add_read_packet(nd, ne2000_can_receive, ne2000_receive, s); | |
| 635 | - | |
| 696 | + s->vc = qemu_new_vlan_client(nd->vlan, ne2000_receive, s); | |
| 697 | + | |
| 698 | + snprintf(s->vc->info_str, sizeof(s->vc->info_str), | |
| 699 | + "ne2000 macaddr=%02x:%02x:%02x:%02x:%02x:%02x", | |
| 700 | + s->macaddr[0], | |
| 701 | + s->macaddr[1], | |
| 702 | + s->macaddr[2], | |
| 703 | + s->macaddr[3], | |
| 704 | + s->macaddr[4], | |
| 705 | + s->macaddr[5]); | |
| 706 | + | |
| 636 | 707 | register_savevm("ne2000", 0, 1, ne2000_save, ne2000_load, s); |
| 637 | - | |
| 638 | 708 | } |
| 639 | 709 | |
| 640 | 710 | /***********************************************************/ |
| ... | ... | @@ -665,7 +735,7 @@ static void ne2000_map(PCIDevice *pci_dev, int region_num, |
| 665 | 735 | register_ioport_read(addr + 0x1f, 1, 1, ne2000_reset_ioport_read, s); |
| 666 | 736 | } |
| 667 | 737 | |
| 668 | -void pci_ne2000_init(PCIBus *bus, NetDriverState *nd) | |
| 738 | +void pci_ne2000_init(PCIBus *bus, NICInfo *nd) | |
| 669 | 739 | { |
| 670 | 740 | PCINE2000State *d; |
| 671 | 741 | NE2000State *s; |
| ... | ... | @@ -690,10 +760,19 @@ void pci_ne2000_init(PCIBus *bus, NetDriverState *nd) |
| 690 | 760 | s = &d->ne2000; |
| 691 | 761 | s->irq = 16; // PCI interrupt |
| 692 | 762 | s->pci_dev = (PCIDevice *)d; |
| 693 | - s->nd = nd; | |
| 763 | + memcpy(s->macaddr, nd->macaddr, 6); | |
| 694 | 764 | ne2000_reset(s); |
| 695 | - qemu_add_read_packet(nd, ne2000_can_receive, ne2000_receive, s); | |
| 696 | - | |
| 765 | + s->vc = qemu_new_vlan_client(nd->vlan, ne2000_receive, s); | |
| 766 | + | |
| 767 | + snprintf(s->vc->info_str, sizeof(s->vc->info_str), | |
| 768 | + "ne2000 pci macaddr=%02x:%02x:%02x:%02x:%02x:%02x", | |
| 769 | + s->macaddr[0], | |
| 770 | + s->macaddr[1], | |
| 771 | + s->macaddr[2], | |
| 772 | + s->macaddr[3], | |
| 773 | + s->macaddr[4], | |
| 774 | + s->macaddr[5]); | |
| 775 | + | |
| 697 | 776 | /* XXX: instance number ? */ |
| 698 | 777 | register_savevm("ne2000", 0, 1, ne2000_save, ne2000_load, s); |
| 699 | 778 | register_savevm("ne2000_pci", 0, 1, generic_pci_save, generic_pci_load, | ... | ... |
hw/parallel.c
| ... | ... | @@ -154,27 +154,6 @@ static uint32_t parallel_ioport_read(void *opaque, uint32_t addr) |
| 154 | 154 | return ret; |
| 155 | 155 | } |
| 156 | 156 | |
| 157 | -static int parallel_can_receive(ParallelState *s) | |
| 158 | -{ | |
| 159 | - return 0; | |
| 160 | -} | |
| 161 | - | |
| 162 | -static void parallel_receive_byte(ParallelState *s, int ch) | |
| 163 | -{ | |
| 164 | -} | |
| 165 | - | |
| 166 | -static int parallel_can_receive1(void *opaque) | |
| 167 | -{ | |
| 168 | - ParallelState *s = opaque; | |
| 169 | - return parallel_can_receive(s); | |
| 170 | -} | |
| 171 | - | |
| 172 | -static void parallel_receive1(void *opaque, const uint8_t *buf, int size) | |
| 173 | -{ | |
| 174 | - ParallelState *s = opaque; | |
| 175 | - parallel_receive_byte(s, buf[0]); | |
| 176 | -} | |
| 177 | - | |
| 178 | 157 | /* If fd is zero, it means that the parallel device uses the console */ |
| 179 | 158 | ParallelState *parallel_init(int base, int irq, CharDriverState *chr) |
| 180 | 159 | { |
| ... | ... | @@ -200,6 +179,5 @@ ParallelState *parallel_init(int base, int irq, CharDriverState *chr) |
| 200 | 179 | |
| 201 | 180 | register_ioport_write(base, 8, 1, parallel_ioport_write, s); |
| 202 | 181 | register_ioport_read(base, 8, 1, parallel_ioport_read, s); |
| 203 | - qemu_chr_add_read_handler(chr, parallel_can_receive1, parallel_receive1, s); | |
| 204 | 182 | return s; |
| 205 | 183 | } | ... | ... |
monitor.c
| ... | ... | @@ -196,23 +196,6 @@ static void do_info_version(void) |
| 196 | 196 | term_printf("%s\n", QEMU_VERSION); |
| 197 | 197 | } |
| 198 | 198 | |
| 199 | -static void do_info_network(void) | |
| 200 | -{ | |
| 201 | - int i, j; | |
| 202 | - NetDriverState *nd; | |
| 203 | - | |
| 204 | - for(i = 0; i < nb_nics; i++) { | |
| 205 | - nd = &nd_table[i]; | |
| 206 | - term_printf("%d: ifname=%s macaddr=", i, nd->ifname); | |
| 207 | - for(j = 0; j < 6; j++) { | |
| 208 | - if (j > 0) | |
| 209 | - term_printf(":"); | |
| 210 | - term_printf("%02x", nd->macaddr[j]); | |
| 211 | - } | |
| 212 | - term_printf("\n"); | |
| 213 | - } | |
| 214 | -} | |
| 215 | - | |
| 216 | 199 | static void do_info_block(void) |
| 217 | 200 | { |
| 218 | 201 | bdrv_info(); | ... | ... |
vl.c
| ... | ... | @@ -40,6 +40,7 @@ |
| 40 | 40 | #include <sys/socket.h> |
| 41 | 41 | #include <netinet/in.h> |
| 42 | 42 | #include <dirent.h> |
| 43 | +#include <netdb.h> | |
| 43 | 44 | #ifdef _BSD |
| 44 | 45 | #include <sys/stat.h> |
| 45 | 46 | #ifndef __APPLE__ |
| ... | ... | @@ -122,10 +123,9 @@ const char* keyboard_layout = NULL; |
| 122 | 123 | int64_t ticks_per_sec; |
| 123 | 124 | int boot_device = 'c'; |
| 124 | 125 | int ram_size; |
| 125 | -static char network_script[1024]; | |
| 126 | 126 | int pit_min_timer_count = 0; |
| 127 | 127 | int nb_nics; |
| 128 | -NetDriverState nd_table[MAX_NICS]; | |
| 128 | +NICInfo nd_table[MAX_NICS]; | |
| 129 | 129 | QEMUTimer *gui_timer; |
| 130 | 130 | int vm_running; |
| 131 | 131 | #ifdef HAS_AUDIO |
| ... | ... | @@ -155,6 +155,7 @@ int win2k_install_hack = 0; |
| 155 | 155 | int usb_enabled = 0; |
| 156 | 156 | USBPort *vm_usb_ports[MAX_VM_USB_PORTS]; |
| 157 | 157 | USBDevice *vm_usb_hub; |
| 158 | +static VLANState *first_vlan; | |
| 158 | 159 | |
| 159 | 160 | /***********************************************************/ |
| 160 | 161 | /* x86 ISA bus support */ |
| ... | ... | @@ -1076,10 +1077,10 @@ CharDriverState *qemu_chr_open_null(void) |
| 1076 | 1077 | |
| 1077 | 1078 | typedef struct { |
| 1078 | 1079 | int fd_in, fd_out; |
| 1079 | - /* for nographic stdio only */ | |
| 1080 | 1080 | IOCanRWHandler *fd_can_read; |
| 1081 | 1081 | IOReadHandler *fd_read; |
| 1082 | 1082 | void *fd_opaque; |
| 1083 | + int max_size; | |
| 1083 | 1084 | } FDCharDriver; |
| 1084 | 1085 | |
| 1085 | 1086 | #define STDIO_MAX_CLIENTS 2 |
| ... | ... | @@ -1113,6 +1114,33 @@ static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len) |
| 1113 | 1114 | return unix_write(s->fd_out, buf, len); |
| 1114 | 1115 | } |
| 1115 | 1116 | |
| 1117 | +static int fd_chr_read_poll(void *opaque) | |
| 1118 | +{ | |
| 1119 | + CharDriverState *chr = opaque; | |
| 1120 | + FDCharDriver *s = chr->opaque; | |
| 1121 | + | |
| 1122 | + s->max_size = s->fd_can_read(s->fd_opaque); | |
| 1123 | + return s->max_size; | |
| 1124 | +} | |
| 1125 | + | |
| 1126 | +static void fd_chr_read(void *opaque) | |
| 1127 | +{ | |
| 1128 | + CharDriverState *chr = opaque; | |
| 1129 | + FDCharDriver *s = chr->opaque; | |
| 1130 | + int size, len; | |
| 1131 | + uint8_t buf[1024]; | |
| 1132 | + | |
| 1133 | + len = sizeof(buf); | |
| 1134 | + if (len > s->max_size) | |
| 1135 | + len = s->max_size; | |
| 1136 | + if (len == 0) | |
| 1137 | + return; | |
| 1138 | + size = read(s->fd_in, buf, len); | |
| 1139 | + if (size > 0) { | |
| 1140 | + s->fd_read(s->fd_opaque, buf, size); | |
| 1141 | + } | |
| 1142 | +} | |
| 1143 | + | |
| 1116 | 1144 | static void fd_chr_add_read_handler(CharDriverState *chr, |
| 1117 | 1145 | IOCanRWHandler *fd_can_read, |
| 1118 | 1146 | IOReadHandler *fd_read, void *opaque) |
| ... | ... | @@ -1120,12 +1148,13 @@ static void fd_chr_add_read_handler(CharDriverState *chr, |
| 1120 | 1148 | FDCharDriver *s = chr->opaque; |
| 1121 | 1149 | |
| 1122 | 1150 | if (s->fd_in >= 0) { |
| 1151 | + s->fd_can_read = fd_can_read; | |
| 1152 | + s->fd_read = fd_read; | |
| 1153 | + s->fd_opaque = opaque; | |
| 1123 | 1154 | if (nographic && s->fd_in == 0) { |
| 1124 | - s->fd_can_read = fd_can_read; | |
| 1125 | - s->fd_read = fd_read; | |
| 1126 | - s->fd_opaque = opaque; | |
| 1127 | 1155 | } else { |
| 1128 | - qemu_add_fd_read_handler(s->fd_in, fd_can_read, fd_read, opaque); | |
| 1156 | + qemu_set_fd_handler2(s->fd_in, fd_chr_read_poll, | |
| 1157 | + fd_chr_read, NULL, chr); | |
| 1129 | 1158 | } |
| 1130 | 1159 | } |
| 1131 | 1160 | } |
| ... | ... | @@ -1261,7 +1290,7 @@ static void stdio_received_byte(int ch) |
| 1261 | 1290 | } |
| 1262 | 1291 | } |
| 1263 | 1292 | |
| 1264 | -static int stdio_can_read(void *opaque) | |
| 1293 | +static int stdio_read_poll(void *opaque) | |
| 1265 | 1294 | { |
| 1266 | 1295 | CharDriverState *chr; |
| 1267 | 1296 | FDCharDriver *s; |
| ... | ... | @@ -1284,11 +1313,14 @@ static int stdio_can_read(void *opaque) |
| 1284 | 1313 | } |
| 1285 | 1314 | } |
| 1286 | 1315 | |
| 1287 | -static void stdio_read(void *opaque, const uint8_t *buf, int size) | |
| 1316 | +static void stdio_read(void *opaque) | |
| 1288 | 1317 | { |
| 1289 | - int i; | |
| 1290 | - for(i = 0; i < size; i++) | |
| 1291 | - stdio_received_byte(buf[i]); | |
| 1318 | + int size; | |
| 1319 | + uint8_t buf[1]; | |
| 1320 | + | |
| 1321 | + size = read(0, buf, 1); | |
| 1322 | + if (size > 0) | |
| 1323 | + stdio_received_byte(buf[0]); | |
| 1292 | 1324 | } |
| 1293 | 1325 | |
| 1294 | 1326 | /* init terminal so that we can grab keys */ |
| ... | ... | @@ -1337,7 +1369,7 @@ CharDriverState *qemu_chr_open_stdio(void) |
| 1337 | 1369 | return NULL; |
| 1338 | 1370 | chr = qemu_chr_open_fd(0, 1); |
| 1339 | 1371 | if (stdio_nb_clients == 0) |
| 1340 | - qemu_add_fd_read_handler(0, stdio_can_read, stdio_read, NULL); | |
| 1372 | + qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, NULL); | |
| 1341 | 1373 | client_index = stdio_nb_clients; |
| 1342 | 1374 | } else { |
| 1343 | 1375 | if (stdio_nb_clients != 0) |
| ... | ... | @@ -1603,7 +1635,7 @@ CharDriverState *qemu_chr_open(const char *filename) |
| 1603 | 1635 | } |
| 1604 | 1636 | |
| 1605 | 1637 | /***********************************************************/ |
| 1606 | -/* Linux network device redirectors */ | |
| 1638 | +/* network device redirectors */ | |
| 1607 | 1639 | |
| 1608 | 1640 | void hex_dump(FILE *f, const uint8_t *buf, int size) |
| 1609 | 1641 | { |
| ... | ... | @@ -1631,107 +1663,171 @@ void hex_dump(FILE *f, const uint8_t *buf, int size) |
| 1631 | 1663 | } |
| 1632 | 1664 | } |
| 1633 | 1665 | |
| 1634 | -void qemu_send_packet(NetDriverState *nd, const uint8_t *buf, int size) | |
| 1666 | +static int parse_macaddr(uint8_t *macaddr, const char *p) | |
| 1635 | 1667 | { |
| 1636 | - nd->send_packet(nd, buf, size); | |
| 1668 | + int i; | |
| 1669 | + for(i = 0; i < 6; i++) { | |
| 1670 | + macaddr[i] = strtol(p, (char **)&p, 16); | |
| 1671 | + if (i == 5) { | |
| 1672 | + if (*p != '\0') | |
| 1673 | + return -1; | |
| 1674 | + } else { | |
| 1675 | + if (*p != ':') | |
| 1676 | + return -1; | |
| 1677 | + p++; | |
| 1678 | + } | |
| 1679 | + } | |
| 1680 | + return 0; | |
| 1637 | 1681 | } |
| 1638 | 1682 | |
| 1639 | -void qemu_add_read_packet(NetDriverState *nd, IOCanRWHandler *fd_can_read, | |
| 1640 | - IOReadHandler *fd_read, void *opaque) | |
| 1683 | +static int get_str_sep(char *buf, int buf_size, const char **pp, int sep) | |
| 1641 | 1684 | { |
| 1642 | - nd->add_read_packet(nd, fd_can_read, fd_read, opaque); | |
| 1685 | + const char *p, *p1; | |
| 1686 | + int len; | |
| 1687 | + p = *pp; | |
| 1688 | + p1 = strchr(p, sep); | |
| 1689 | + if (!p1) | |
| 1690 | + return -1; | |
| 1691 | + len = p1 - p; | |
| 1692 | + p1++; | |
| 1693 | + if (buf_size > 0) { | |
| 1694 | + if (len > buf_size - 1) | |
| 1695 | + len = buf_size - 1; | |
| 1696 | + memcpy(buf, p, len); | |
| 1697 | + buf[len] = '\0'; | |
| 1698 | + } | |
| 1699 | + *pp = p1; | |
| 1700 | + return 0; | |
| 1643 | 1701 | } |
| 1644 | 1702 | |
| 1645 | -/* dummy network adapter */ | |
| 1703 | +int parse_host_port(struct sockaddr_in *saddr, const char *str) | |
| 1704 | +{ | |
| 1705 | + char buf[512]; | |
| 1706 | + struct hostent *he; | |
| 1707 | + const char *p, *r; | |
| 1708 | + int port; | |
| 1709 | + | |
| 1710 | + p = str; | |
| 1711 | + if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) | |
| 1712 | + return -1; | |
| 1713 | + saddr->sin_family = AF_INET; | |
| 1714 | + if (buf[0] == '\0') { | |
| 1715 | + saddr->sin_addr.s_addr = 0; | |
| 1716 | + } else { | |
| 1717 | + if (isdigit(buf[0])) { | |
| 1718 | + if (!inet_aton(buf, &saddr->sin_addr)) | |
| 1719 | + return -1; | |
| 1720 | + } else { | |
| 1721 | +#ifdef _WIN32 | |
| 1722 | + return -1; | |
| 1723 | +#else | |
| 1724 | + if ((he = gethostbyname(buf)) == NULL) | |
| 1725 | + return - 1; | |
| 1726 | + saddr->sin_addr = *(struct in_addr *)he->h_addr; | |
| 1727 | +#endif | |
| 1728 | + } | |
| 1729 | + } | |
| 1730 | + port = strtol(p, (char **)&r, 0); | |
| 1731 | + if (r == p) | |
| 1732 | + return -1; | |
| 1733 | + saddr->sin_port = htons(port); | |
| 1734 | + return 0; | |
| 1735 | +} | |
| 1646 | 1736 | |
| 1647 | -static void dummy_send_packet(NetDriverState *nd, const uint8_t *buf, int size) | |
| 1737 | +/* find or alloc a new VLAN */ | |
| 1738 | +VLANState *qemu_find_vlan(int id) | |
| 1648 | 1739 | { |
| 1740 | + VLANState **pvlan, *vlan; | |
| 1741 | + for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) { | |
| 1742 | + if (vlan->id == id) | |
| 1743 | + return vlan; | |
| 1744 | + } | |
| 1745 | + vlan = qemu_mallocz(sizeof(VLANState)); | |
| 1746 | + if (!vlan) | |
| 1747 | + return NULL; | |
| 1748 | + vlan->id = id; | |
| 1749 | + vlan->next = NULL; | |
| 1750 | + pvlan = &first_vlan; | |
| 1751 | + while (*pvlan != NULL) | |
| 1752 | + pvlan = &(*pvlan)->next; | |
| 1753 | + *pvlan = vlan; | |
| 1754 | + return vlan; | |
| 1649 | 1755 | } |
| 1650 | 1756 | |
| 1651 | -static void dummy_add_read_packet(NetDriverState *nd, | |
| 1652 | - IOCanRWHandler *fd_can_read, | |
| 1653 | - IOReadHandler *fd_read, void *opaque) | |
| 1757 | +VLANClientState *qemu_new_vlan_client(VLANState *vlan, | |
| 1758 | + IOReadHandler *fd_read, void *opaque) | |
| 1654 | 1759 | { |
| 1760 | + VLANClientState *vc, **pvc; | |
| 1761 | + vc = qemu_mallocz(sizeof(VLANClientState)); | |
| 1762 | + if (!vc) | |
| 1763 | + return NULL; | |
| 1764 | + vc->fd_read = fd_read; | |
| 1765 | + vc->opaque = opaque; | |
| 1766 | + vc->vlan = vlan; | |
| 1767 | + | |
| 1768 | + vc->next = NULL; | |
| 1769 | + pvc = &vlan->first_client; | |
| 1770 | + while (*pvc != NULL) | |
| 1771 | + pvc = &(*pvc)->next; | |
| 1772 | + *pvc = vc; | |
| 1773 | + return vc; | |
| 1655 | 1774 | } |
| 1656 | 1775 | |
| 1657 | -static int net_dummy_init(NetDriverState *nd) | |
| 1776 | +void qemu_send_packet(VLANClientState *vc1, const uint8_t *buf, int size) | |
| 1658 | 1777 | { |
| 1659 | - nd->send_packet = dummy_send_packet; | |
| 1660 | - nd->add_read_packet = dummy_add_read_packet; | |
| 1661 | - pstrcpy(nd->ifname, sizeof(nd->ifname), "dummy"); | |
| 1662 | - return 0; | |
| 1778 | + VLANState *vlan = vc1->vlan; | |
| 1779 | + VLANClientState *vc; | |
| 1780 | + | |
| 1781 | +#if 0 | |
| 1782 | + printf("vlan %d send:\n", vlan->id); | |
| 1783 | + hex_dump(stdout, buf, size); | |
| 1784 | +#endif | |
| 1785 | + for(vc = vlan->first_client; vc != NULL; vc = vc->next) { | |
| 1786 | + if (vc != vc1) { | |
| 1787 | + vc->fd_read(vc->opaque, buf, size); | |
| 1788 | + } | |
| 1789 | + } | |
| 1663 | 1790 | } |
| 1664 | 1791 | |
| 1665 | 1792 | #if defined(CONFIG_SLIRP) |
| 1666 | 1793 | |
| 1667 | 1794 | /* slirp network adapter */ |
| 1668 | 1795 | |
| 1669 | -static void *slirp_fd_opaque; | |
| 1670 | -static IOCanRWHandler *slirp_fd_can_read; | |
| 1671 | -static IOReadHandler *slirp_fd_read; | |
| 1672 | 1796 | static int slirp_inited; |
| 1797 | +static VLANClientState *slirp_vc; | |
| 1673 | 1798 | |
| 1674 | 1799 | int slirp_can_output(void) |
| 1675 | 1800 | { |
| 1676 | - return slirp_fd_can_read(slirp_fd_opaque); | |
| 1801 | + return 1; | |
| 1677 | 1802 | } |
| 1678 | 1803 | |
| 1679 | 1804 | void slirp_output(const uint8_t *pkt, int pkt_len) |
| 1680 | 1805 | { |
| 1681 | 1806 | #if 0 |
| 1682 | - printf("output:\n"); | |
| 1807 | + printf("slirp output:\n"); | |
| 1683 | 1808 | hex_dump(stdout, pkt, pkt_len); |
| 1684 | 1809 | #endif |
| 1685 | - slirp_fd_read(slirp_fd_opaque, pkt, pkt_len); | |
| 1810 | + qemu_send_packet(slirp_vc, pkt, pkt_len); | |
| 1686 | 1811 | } |
| 1687 | 1812 | |
| 1688 | -static void slirp_send_packet(NetDriverState *nd, const uint8_t *buf, int size) | |
| 1813 | +static void slirp_receive(void *opaque, const uint8_t *buf, int size) | |
| 1689 | 1814 | { |
| 1690 | 1815 | #if 0 |
| 1691 | - printf("input:\n"); | |
| 1816 | + printf("slirp input:\n"); | |
| 1692 | 1817 | hex_dump(stdout, buf, size); |
| 1693 | 1818 | #endif |
| 1694 | 1819 | slirp_input(buf, size); |
| 1695 | 1820 | } |
| 1696 | 1821 | |
| 1697 | -static void slirp_add_read_packet(NetDriverState *nd, | |
| 1698 | - IOCanRWHandler *fd_can_read, | |
| 1699 | - IOReadHandler *fd_read, void *opaque) | |
| 1700 | -{ | |
| 1701 | - slirp_fd_opaque = opaque; | |
| 1702 | - slirp_fd_can_read = fd_can_read; | |
| 1703 | - slirp_fd_read = fd_read; | |
| 1704 | -} | |
| 1705 | - | |
| 1706 | -static int net_slirp_init(NetDriverState *nd) | |
| 1822 | +static int net_slirp_init(VLANState *vlan) | |
| 1707 | 1823 | { |
| 1708 | 1824 | if (!slirp_inited) { |
| 1709 | 1825 | slirp_inited = 1; |
| 1710 | 1826 | slirp_init(); |
| 1711 | 1827 | } |
| 1712 | - nd->send_packet = slirp_send_packet; | |
| 1713 | - nd->add_read_packet = slirp_add_read_packet; | |
| 1714 | - pstrcpy(nd->ifname, sizeof(nd->ifname), "slirp"); | |
| 1715 | - return 0; | |
| 1716 | -} | |
| 1717 | - | |
| 1718 | -static int get_str_sep(char *buf, int buf_size, const char **pp, int sep) | |
| 1719 | -{ | |
| 1720 | - const char *p, *p1; | |
| 1721 | - int len; | |
| 1722 | - p = *pp; | |
| 1723 | - p1 = strchr(p, sep); | |
| 1724 | - if (!p1) | |
| 1725 | - return -1; | |
| 1726 | - len = p1 - p; | |
| 1727 | - p1++; | |
| 1728 | - if (buf_size > 0) { | |
| 1729 | - if (len > buf_size - 1) | |
| 1730 | - len = buf_size - 1; | |
| 1731 | - memcpy(buf, p, len); | |
| 1732 | - buf[len] = '\0'; | |
| 1733 | - } | |
| 1734 | - *pp = p1; | |
| 1828 | + slirp_vc = qemu_new_vlan_client(vlan, | |
| 1829 | + slirp_receive, NULL); | |
| 1830 | + snprintf(slirp_vc->info_str, sizeof(slirp_vc->info_str), "user redirector"); | |
| 1735 | 1831 | return 0; |
| 1736 | 1832 | } |
| 1737 | 1833 | |
| ... | ... | @@ -1874,8 +1970,55 @@ void net_slirp_smb(const char *exported_dir) |
| 1874 | 1970 | #endif /* CONFIG_SLIRP */ |
| 1875 | 1971 | |
| 1876 | 1972 | #if !defined(_WIN32) |
| 1973 | + | |
| 1974 | +typedef struct TAPState { | |
| 1975 | + VLANClientState *vc; | |
| 1976 | + int fd; | |
| 1977 | +} TAPState; | |
| 1978 | + | |
| 1979 | +static void tap_receive(void *opaque, const uint8_t *buf, int size) | |
| 1980 | +{ | |
| 1981 | + TAPState *s = opaque; | |
| 1982 | + int ret; | |
| 1983 | + for(;;) { | |
| 1984 | + ret = write(s->fd, buf, size); | |
| 1985 | + if (ret < 0 && (errno == EINTR || errno == EAGAIN)) { | |
| 1986 | + } else { | |
| 1987 | + break; | |
| 1988 | + } | |
| 1989 | + } | |
| 1990 | +} | |
| 1991 | + | |
| 1992 | +static void tap_send(void *opaque) | |
| 1993 | +{ | |
| 1994 | + TAPState *s = opaque; | |
| 1995 | + uint8_t buf[4096]; | |
| 1996 | + int size; | |
| 1997 | + | |
| 1998 | + size = read(s->fd, buf, sizeof(buf)); | |
| 1999 | + if (size > 0) { | |
| 2000 | + qemu_send_packet(s->vc, buf, size); | |
| 2001 | + } | |
| 2002 | +} | |
| 2003 | + | |
| 2004 | +/* fd support */ | |
| 2005 | + | |
| 2006 | +static TAPState *net_tap_fd_init(VLANState *vlan, int fd) | |
| 2007 | +{ | |
| 2008 | + TAPState *s; | |
| 2009 | + | |
| 2010 | + s = qemu_mallocz(sizeof(TAPState)); | |
| 2011 | + if (!s) | |
| 2012 | + return NULL; | |
| 2013 | + s->fd = fd; | |
| 2014 | + s->vc = qemu_new_vlan_client(vlan, tap_receive, s); | |
| 2015 | + qemu_set_fd_handler(s->fd, tap_send, NULL, s); | |
| 2016 | + snprintf(s->vc->info_str, sizeof(s->vc->info_str), "tap: fd=%d", fd); | |
| 2017 | + return s; | |
| 2018 | +} | |
| 2019 | + | |
| 1877 | 2020 | #ifdef _BSD |
| 1878 | -static int tun_open(char *ifname, int ifname_size) | |
| 2021 | +static int tap_open(char *ifname, int ifname_size) | |
| 1879 | 2022 | { |
| 1880 | 2023 | int fd; |
| 1881 | 2024 | char *dev; |
| ... | ... | @@ -1895,7 +2038,7 @@ static int tun_open(char *ifname, int ifname_size) |
| 1895 | 2038 | return fd; |
| 1896 | 2039 | } |
| 1897 | 2040 | #else |
| 1898 | -static int tun_open(char *ifname, int ifname_size) | |
| 2041 | +static int tap_open(char *ifname, int ifname_size) | |
| 1899 | 2042 | { |
| 1900 | 2043 | struct ifreq ifr; |
| 1901 | 2044 | int fd, ret; |
| ... | ... | @@ -1907,76 +2050,448 @@ static int tun_open(char *ifname, int ifname_size) |
| 1907 | 2050 | } |
| 1908 | 2051 | memset(&ifr, 0, sizeof(ifr)); |
| 1909 | 2052 | ifr.ifr_flags = IFF_TAP | IFF_NO_PI; |
| 1910 | - pstrcpy(ifr.ifr_name, IFNAMSIZ, "tun%d"); | |
| 2053 | + if (ifname[0] != '\0') | |
| 2054 | + pstrcpy(ifr.ifr_name, IFNAMSIZ, ifname); | |
| 2055 | + else | |
| 2056 | + pstrcpy(ifr.ifr_name, IFNAMSIZ, "tap%d"); | |
| 1911 | 2057 | ret = ioctl(fd, TUNSETIFF, (void *) &ifr); |
| 1912 | 2058 | if (ret != 0) { |
| 1913 | 2059 | fprintf(stderr, "warning: could not configure /dev/net/tun: no virtual network emulation\n"); |
| 1914 | 2060 | close(fd); |
| 1915 | 2061 | return -1; |
| 1916 | 2062 | } |
| 1917 | - printf("Connected to host network interface: %s\n", ifr.ifr_name); | |
| 1918 | 2063 | pstrcpy(ifname, ifname_size, ifr.ifr_name); |
| 1919 | 2064 | fcntl(fd, F_SETFL, O_NONBLOCK); |
| 1920 | 2065 | return fd; |
| 1921 | 2066 | } |
| 1922 | 2067 | #endif |
| 1923 | 2068 | |
| 1924 | -static void tun_send_packet(NetDriverState *nd, const uint8_t *buf, int size) | |
| 2069 | +static int net_tap_init(VLANState *vlan, const char *ifname1, | |
| 2070 | + const char *setup_script) | |
| 2071 | +{ | |
| 2072 | + TAPState *s; | |
| 2073 | + int pid, status, fd; | |
| 2074 | + char *args[3]; | |
| 2075 | + char **parg; | |
| 2076 | + char ifname[128]; | |
| 2077 | + | |
| 2078 | + if (ifname1 != NULL) | |
| 2079 | + pstrcpy(ifname, sizeof(ifname), ifname1); | |
| 2080 | + else | |
| 2081 | + ifname[0] = '\0'; | |
| 2082 | + fd = tap_open(ifname, sizeof(ifname)); | |
| 2083 | + if (fd < 0) | |
| 2084 | + return -1; | |
| 2085 | + | |
| 2086 | + if (!setup_script) | |
| 2087 | + setup_script = ""; | |
| 2088 | + if (setup_script[0] != '\0') { | |
| 2089 | + /* try to launch network init script */ | |
| 2090 | + pid = fork(); | |
| 2091 | + if (pid >= 0) { | |
| 2092 | + if (pid == 0) { | |
| 2093 | + parg = args; | |
| 2094 | + *parg++ = (char *)setup_script; | |
| 2095 | + *parg++ = ifname; | |
| 2096 | + *parg++ = NULL; | |
| 2097 | + execv(setup_script, args); | |
| 2098 | + exit(1); | |
| 2099 | + } | |
| 2100 | + while (waitpid(pid, &status, 0) != pid); | |
| 2101 | + if (!WIFEXITED(status) || | |
| 2102 | + WEXITSTATUS(status) != 0) { | |
| 2103 | + fprintf(stderr, "%s: could not launch network script\n", | |
| 2104 | + setup_script); | |
| 2105 | + return -1; | |
| 2106 | + } | |
| 2107 | + } | |
| 2108 | + } | |
| 2109 | + s = net_tap_fd_init(vlan, fd); | |
| 2110 | + if (!s) | |
| 2111 | + return -1; | |
| 2112 | + snprintf(s->vc->info_str, sizeof(s->vc->info_str), | |
| 2113 | + "tap: ifname=%s setup_script=%s", ifname, setup_script); | |
| 2114 | + return 0; | |
| 2115 | +} | |
| 2116 | + | |
| 2117 | +/* network connection */ | |
| 2118 | +typedef struct NetSocketState { | |
| 2119 | + VLANClientState *vc; | |
| 2120 | + int fd; | |
| 2121 | + int state; /* 0 = getting length, 1 = getting data */ | |
| 2122 | + int index; | |
| 2123 | + int packet_len; | |
| 2124 | + uint8_t buf[4096]; | |
| 2125 | +} NetSocketState; | |
| 2126 | + | |
| 2127 | +typedef struct NetSocketListenState { | |
| 2128 | + VLANState *vlan; | |
| 2129 | + int fd; | |
| 2130 | +} NetSocketListenState; | |
| 2131 | + | |
| 2132 | +/* XXX: we consider we can send the whole packet without blocking */ | |
| 2133 | +static void net_socket_receive(void *opaque, const uint8_t *buf, int size) | |
| 1925 | 2134 | { |
| 1926 | - write(nd->fd, buf, size); | |
| 2135 | + NetSocketState *s = opaque; | |
| 2136 | + uint32_t len; | |
| 2137 | + len = htonl(size); | |
| 2138 | + | |
| 2139 | + unix_write(s->fd, (const uint8_t *)&len, sizeof(len)); | |
| 2140 | + unix_write(s->fd, buf, size); | |
| 1927 | 2141 | } |
| 1928 | 2142 | |
| 1929 | -static void tun_add_read_packet(NetDriverState *nd, | |
| 1930 | - IOCanRWHandler *fd_can_read, | |
| 1931 | - IOReadHandler *fd_read, void *opaque) | |
| 2143 | +static void net_socket_send(void *opaque) | |
| 1932 | 2144 | { |
| 1933 | - qemu_add_fd_read_handler(nd->fd, fd_can_read, fd_read, opaque); | |
| 2145 | + NetSocketState *s = opaque; | |
| 2146 | + int l, size; | |
| 2147 | + uint8_t buf1[4096]; | |
| 2148 | + const uint8_t *buf; | |
| 2149 | + | |
| 2150 | + size = read(s->fd, buf1, sizeof(buf1)); | |
| 2151 | + if (size < 0) | |
| 2152 | + return; | |
| 2153 | + if (size == 0) { | |
| 2154 | + /* end of connection */ | |
| 2155 | + qemu_set_fd_handler(s->fd, NULL, NULL, NULL); | |
| 2156 | + return; | |
| 2157 | + } | |
| 2158 | + buf = buf1; | |
| 2159 | + while (size > 0) { | |
| 2160 | + /* reassemble a packet from the network */ | |
| 2161 | + switch(s->state) { | |
| 2162 | + case 0: | |
| 2163 | + l = 4 - s->index; | |
| 2164 | + if (l > size) | |
| 2165 | + l = size; | |
| 2166 | + memcpy(s->buf + s->index, buf, l); | |
| 2167 | + buf += l; | |
| 2168 | + size -= l; | |
| 2169 | + s->index += l; | |
| 2170 | + if (s->index == 4) { | |
| 2171 | + /* got length */ | |
| 2172 | + s->packet_len = ntohl(*(uint32_t *)s->buf); | |
| 2173 | + s->index = 0; | |
| 2174 | + s->state = 1; | |
| 2175 | + } | |
| 2176 | + break; | |
| 2177 | + case 1: | |
| 2178 | + l = s->packet_len - s->index; | |
| 2179 | + if (l > size) | |
| 2180 | + l = size; | |
| 2181 | + memcpy(s->buf + s->index, buf, l); | |
| 2182 | + s->index += l; | |
| 2183 | + buf += l; | |
| 2184 | + size -= l; | |
| 2185 | + if (s->index >= s->packet_len) { | |
| 2186 | + qemu_send_packet(s->vc, s->buf, s->packet_len); | |
| 2187 | + s->index = 0; | |
| 2188 | + s->state = 0; | |
| 2189 | + } | |
| 2190 | + break; | |
| 2191 | + } | |
| 2192 | + } | |
| 1934 | 2193 | } |
| 1935 | 2194 | |
| 1936 | -static int net_tun_init(NetDriverState *nd) | |
| 2195 | +static void net_socket_connect(void *opaque) | |
| 1937 | 2196 | { |
| 1938 | - int pid, status; | |
| 1939 | - char *args[3]; | |
| 1940 | - char **parg; | |
| 2197 | + NetSocketState *s = opaque; | |
| 2198 | + qemu_set_fd_handler(s->fd, net_socket_send, NULL, s); | |
| 2199 | +} | |
| 1941 | 2200 | |
| 1942 | - nd->fd = tun_open(nd->ifname, sizeof(nd->ifname)); | |
| 1943 | - if (nd->fd < 0) | |
| 1944 | - return -1; | |
| 2201 | +static NetSocketState *net_socket_fd_init(VLANState *vlan, int fd, | |
| 2202 | + int is_connected) | |
| 2203 | +{ | |
| 2204 | + NetSocketState *s; | |
| 2205 | + s = qemu_mallocz(sizeof(NetSocketState)); | |
| 2206 | + if (!s) | |
| 2207 | + return NULL; | |
| 2208 | + s->fd = fd; | |
| 2209 | + s->vc = qemu_new_vlan_client(vlan, | |
| 2210 | + net_socket_receive, s); | |
| 2211 | + snprintf(s->vc->info_str, sizeof(s->vc->info_str), | |
| 2212 | + "socket: fd=%d", fd); | |
| 2213 | + if (is_connected) { | |
| 2214 | + net_socket_connect(s); | |
| 2215 | + } else { | |
| 2216 | + qemu_set_fd_handler(s->fd, NULL, net_socket_connect, s); | |
| 2217 | + } | |
| 2218 | + return s; | |
| 2219 | +} | |
| 1945 | 2220 | |
| 1946 | - /* try to launch network init script */ | |
| 1947 | - pid = fork(); | |
| 1948 | - if (pid >= 0) { | |
| 1949 | - if (pid == 0) { | |
| 1950 | - parg = args; | |
| 1951 | - *parg++ = network_script; | |
| 1952 | - *parg++ = nd->ifname; | |
| 1953 | - *parg++ = NULL; | |
| 1954 | - execv(network_script, args); | |
| 1955 | - exit(1); | |
| 1956 | - } | |
| 1957 | - while (waitpid(pid, &status, 0) != pid); | |
| 1958 | - if (!WIFEXITED(status) || | |
| 1959 | - WEXITSTATUS(status) != 0) { | |
| 1960 | - fprintf(stderr, "%s: could not launch network script\n", | |
| 1961 | - network_script); | |
| 2221 | +static void net_socket_accept(void *opaque) | |
| 2222 | +{ | |
| 2223 | + NetSocketListenState *s = opaque; | |
| 2224 | + NetSocketState *s1; | |
| 2225 | + struct sockaddr_in saddr; | |
| 2226 | + socklen_t len; | |
| 2227 | + int fd; | |
| 2228 | + | |
| 2229 | + for(;;) { | |
| 2230 | + len = sizeof(saddr); | |
| 2231 | + fd = accept(s->fd, (struct sockaddr *)&saddr, &len); | |
| 2232 | + if (fd < 0 && errno != EINTR) { | |
| 2233 | + return; | |
| 2234 | + } else if (fd >= 0) { | |
| 2235 | + break; | |
| 1962 | 2236 | } |
| 1963 | 2237 | } |
| 1964 | - nd->send_packet = tun_send_packet; | |
| 1965 | - nd->add_read_packet = tun_add_read_packet; | |
| 2238 | + s1 = net_socket_fd_init(s->vlan, fd, 1); | |
| 2239 | + if (!s1) { | |
| 2240 | + close(fd); | |
| 2241 | + } else { | |
| 2242 | + snprintf(s1->vc->info_str, sizeof(s1->vc->info_str), | |
| 2243 | + "socket: connection from %s:%d", | |
| 2244 | + inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); | |
| 2245 | + } | |
| 2246 | +} | |
| 2247 | + | |
| 2248 | +static int net_socket_listen_init(VLANState *vlan, const char *host_str) | |
| 2249 | +{ | |
| 2250 | + NetSocketListenState *s; | |
| 2251 | + int fd, val, ret; | |
| 2252 | + struct sockaddr_in saddr; | |
| 2253 | + | |
| 2254 | + if (parse_host_port(&saddr, host_str) < 0) | |
| 2255 | + return -1; | |
| 2256 | + | |
| 2257 | + s = qemu_mallocz(sizeof(NetSocketListenState)); | |
| 2258 | + if (!s) | |
| 2259 | + return -1; | |
| 2260 | + | |
| 2261 | + fd = socket(PF_INET, SOCK_STREAM, 0); | |
| 2262 | + if (fd < 0) { | |
| 2263 | + perror("socket"); | |
| 2264 | + return -1; | |
| 2265 | + } | |
| 2266 | + fcntl(fd, F_SETFL, O_NONBLOCK); | |
| 2267 | + | |
| 2268 | + /* allow fast reuse */ | |
| 2269 | + val = 1; | |
| 2270 | + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); | |
| 2271 | + | |
| 2272 | + ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)); | |
| 2273 | + if (ret < 0) { | |
| 2274 | + perror("bind"); | |
| 2275 | + return -1; | |
| 2276 | + } | |
| 2277 | + ret = listen(fd, 0); | |
| 2278 | + if (ret < 0) { | |
| 2279 | + perror("listen"); | |
| 2280 | + return -1; | |
| 2281 | + } | |
| 2282 | + s->vlan = vlan; | |
| 2283 | + s->fd = fd; | |
| 2284 | + qemu_set_fd_handler(fd, net_socket_accept, NULL, s); | |
| 1966 | 2285 | return 0; |
| 1967 | 2286 | } |
| 1968 | 2287 | |
| 1969 | -static int net_fd_init(NetDriverState *nd, int fd) | |
| 2288 | +static int net_socket_connect_init(VLANState *vlan, const char *host_str) | |
| 1970 | 2289 | { |
| 1971 | - nd->fd = fd; | |
| 1972 | - nd->send_packet = tun_send_packet; | |
| 1973 | - nd->add_read_packet = tun_add_read_packet; | |
| 1974 | - pstrcpy(nd->ifname, sizeof(nd->ifname), "tunfd"); | |
| 2290 | + NetSocketState *s; | |
| 2291 | + int fd, connected, ret; | |
| 2292 | + struct sockaddr_in saddr; | |
| 2293 | + | |
| 2294 | + if (parse_host_port(&saddr, host_str) < 0) | |
| 2295 | + return -1; | |
| 2296 | + | |
| 2297 | + fd = socket(PF_INET, SOCK_STREAM, 0); | |
| 2298 | + if (fd < 0) { | |
| 2299 | + perror("socket"); | |
| 2300 | + return -1; | |
| 2301 | + } | |
| 2302 | + fcntl(fd, F_SETFL, O_NONBLOCK); | |
| 2303 | + | |
| 2304 | + connected = 0; | |
| 2305 | + for(;;) { | |
| 2306 | + ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr)); | |
| 2307 | + if (ret < 0) { | |
| 2308 | + if (errno == EINTR || errno == EAGAIN) { | |
| 2309 | + } else if (errno == EINPROGRESS) { | |
| 2310 | + break; | |
| 2311 | + } else { | |
| 2312 | + perror("connect"); | |
| 2313 | + close(fd); | |
| 2314 | + return -1; | |
| 2315 | + } | |
| 2316 | + } else { | |
| 2317 | + connected = 1; | |
| 2318 | + break; | |
| 2319 | + } | |
| 2320 | + } | |
| 2321 | + s = net_socket_fd_init(vlan, fd, connected); | |
| 2322 | + if (!s) | |
| 2323 | + return -1; | |
| 2324 | + snprintf(s->vc->info_str, sizeof(s->vc->info_str), | |
| 2325 | + "socket: connect to %s:%d", | |
| 2326 | + inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); | |
| 1975 | 2327 | return 0; |
| 1976 | 2328 | } |
| 1977 | 2329 | |
| 1978 | 2330 | #endif /* !_WIN32 */ |
| 1979 | 2331 | |
| 2332 | +static int get_param_value(char *buf, int buf_size, | |
| 2333 | + const char *tag, const char *str) | |
| 2334 | +{ | |
| 2335 | + const char *p; | |
| 2336 | + char *q; | |
| 2337 | + char option[128]; | |
| 2338 | + | |
| 2339 | + p = str; | |
| 2340 | + for(;;) { | |
| 2341 | + q = option; | |
| 2342 | + while (*p != '\0' && *p != '=') { | |
| 2343 | + if ((q - option) < sizeof(option) - 1) | |
| 2344 | + *q++ = *p; | |
| 2345 | + p++; | |
| 2346 | + } | |
| 2347 | + *q = '\0'; | |
| 2348 | + if (*p != '=') | |
| 2349 | + break; | |
| 2350 | + p++; | |
| 2351 | + if (!strcmp(tag, option)) { | |
| 2352 | + q = buf; | |
| 2353 | + while (*p != '\0' && *p != ',') { | |
| 2354 | + if ((q - buf) < buf_size - 1) | |
| 2355 | + *q++ = *p; | |
| 2356 | + p++; | |
| 2357 | + } | |
| 2358 | + *q = '\0'; | |
| 2359 | + return q - buf; | |
| 2360 | + } else { | |
| 2361 | + while (*p != '\0' && *p != ',') { | |
| 2362 | + p++; | |
| 2363 | + } | |
| 2364 | + } | |
| 2365 | + if (*p != ',') | |
| 2366 | + break; | |
| 2367 | + p++; | |
| 2368 | + } | |
| 2369 | + return 0; | |
| 2370 | +} | |
| 2371 | + | |
| 2372 | +int net_client_init(const char *str) | |
| 2373 | +{ | |
| 2374 | + const char *p; | |
| 2375 | + char *q; | |
| 2376 | + char device[64]; | |
| 2377 | + char buf[1024]; | |
| 2378 | + int vlan_id, ret; | |
| 2379 | + VLANState *vlan; | |
| 2380 | + | |
| 2381 | + p = str; | |
| 2382 | + q = device; | |
| 2383 | + while (*p != '\0' && *p != ',') { | |
| 2384 | + if ((q - device) < sizeof(device) - 1) | |
| 2385 | + *q++ = *p; | |
| 2386 | + p++; | |
| 2387 | + } | |
| 2388 | + *q = '\0'; | |
| 2389 | + if (*p == ',') | |
| 2390 | + p++; | |
| 2391 | + vlan_id = 0; | |
| 2392 | + if (get_param_value(buf, sizeof(buf), "vlan", p)) { | |
| 2393 | + vlan_id = strtol(buf, NULL, 0); | |
| 2394 | + } | |
| 2395 | + vlan = qemu_find_vlan(vlan_id); | |
| 2396 | + if (!vlan) { | |
| 2397 | + fprintf(stderr, "Could not create vlan %d\n", vlan_id); | |
| 2398 | + return -1; | |
| 2399 | + } | |
| 2400 | + if (!strcmp(device, "nic")) { | |
| 2401 | + NICInfo *nd; | |
| 2402 | + uint8_t *macaddr; | |
| 2403 | + | |
| 2404 | + if (nb_nics >= MAX_NICS) { | |
| 2405 | + fprintf(stderr, "Too Many NICs\n"); | |
| 2406 | + return -1; | |
| 2407 | + } | |
| 2408 | + nd = &nd_table[nb_nics]; | |
| 2409 | + macaddr = nd->macaddr; | |
| 2410 | + macaddr[0] = 0x52; | |
| 2411 | + macaddr[1] = 0x54; | |
| 2412 | + macaddr[2] = 0x00; | |
| 2413 | + macaddr[3] = 0x12; | |
| 2414 | + macaddr[4] = 0x34; | |
| 2415 | + macaddr[5] = 0x56 + nb_nics; | |
| 2416 | + | |
| 2417 | + if (get_param_value(buf, sizeof(buf), "macaddr", p)) { | |
| 2418 | + if (parse_macaddr(macaddr, buf) < 0) { | |
| 2419 | + fprintf(stderr, "invalid syntax for ethernet address\n"); | |
| 2420 | + return -1; | |
| 2421 | + } | |
| 2422 | + } | |
| 2423 | + nd->vlan = vlan; | |
| 2424 | + nb_nics++; | |
| 2425 | + ret = 0; | |
| 2426 | + } else | |
| 2427 | + if (!strcmp(device, "none")) { | |
| 2428 | + /* does nothing. It is needed to signal that no network cards | |
| 2429 | + are wanted */ | |
| 2430 | + ret = 0; | |
| 2431 | + } else | |
| 2432 | +#ifdef CONFIG_SLIRP | |
| 2433 | + if (!strcmp(device, "user")) { | |
| 2434 | + ret = net_slirp_init(vlan); | |
| 2435 | + } else | |
| 2436 | +#endif | |
| 2437 | +#ifndef _WIN32 | |
| 2438 | + if (!strcmp(device, "tap")) { | |
| 2439 | + char ifname[64]; | |
| 2440 | + char setup_script[1024]; | |
| 2441 | + int fd; | |
| 2442 | + if (get_param_value(buf, sizeof(buf), "fd", p) > 0) { | |
| 2443 | + fd = strtol(buf, NULL, 0); | |
| 2444 | + ret = -1; | |
| 2445 | + if (net_tap_fd_init(vlan, fd)) | |
| 2446 | + ret = 0; | |
| 2447 | + } else { | |
| 2448 | + get_param_value(ifname, sizeof(ifname), "ifname", p); | |
| 2449 | + if (get_param_value(setup_script, sizeof(setup_script), "script", p) == 0) { | |
| 2450 | + pstrcpy(setup_script, sizeof(setup_script), DEFAULT_NETWORK_SCRIPT); | |
| 2451 | + } | |
| 2452 | + ret = net_tap_init(vlan, ifname, setup_script); | |
| 2453 | + } | |
| 2454 | + } else | |
| 2455 | + if (!strcmp(device, "socket")) { | |
| 2456 | + if (get_param_value(buf, sizeof(buf), "fd", p) > 0) { | |
| 2457 | + int fd; | |
| 2458 | + fd = strtol(buf, NULL, 0); | |
| 2459 | + ret = -1; | |
| 2460 | + if (net_socket_fd_init(vlan, fd, 1)) | |
| 2461 | + ret = 0; | |
| 2462 | + } else if (get_param_value(buf, sizeof(buf), "listen", p) > 0) { | |
| 2463 | + ret = net_socket_listen_init(vlan, buf); | |
| 2464 | + } else if (get_param_value(buf, sizeof(buf), "connect", p) > 0) { | |
| 2465 | + ret = net_socket_connect_init(vlan, buf); | |
| 2466 | + } else { | |
| 2467 | + fprintf(stderr, "Unknown socket options: %s\n", p); | |
| 2468 | + return -1; | |
| 2469 | + } | |
| 2470 | + } else | |
| 2471 | +#endif | |
| 2472 | + { | |
| 2473 | + fprintf(stderr, "Unknown network device: %s\n", device); | |
| 2474 | + return -1; | |
| 2475 | + } | |
| 2476 | + if (ret < 0) { | |
| 2477 | + fprintf(stderr, "Could not initialize device '%s'\n", device); | |
| 2478 | + } | |
| 2479 | + | |
| 2480 | + return ret; | |
| 2481 | +} | |
| 2482 | + | |
| 2483 | +void do_info_network(void) | |
| 2484 | +{ | |
| 2485 | + VLANState *vlan; | |
| 2486 | + VLANClientState *vc; | |
| 2487 | + | |
| 2488 | + for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) { | |
| 2489 | + term_printf("VLAN %d devices:\n", vlan->id); | |
| 2490 | + for(vc = vlan->first_client; vc != NULL; vc = vc->next) | |
| 2491 | + term_printf(" %s\n", vc->info_str); | |
| 2492 | + } | |
| 2493 | +} | |
| 2494 | + | |
| 1980 | 2495 | /***********************************************************/ |
| 1981 | 2496 | /* USB devices */ |
| 1982 | 2497 | |
| ... | ... | @@ -2175,49 +2690,65 @@ static void host_segv_handler(int host_signum, siginfo_t *info, |
| 2175 | 2690 | |
| 2176 | 2691 | typedef struct IOHandlerRecord { |
| 2177 | 2692 | int fd; |
| 2178 | - IOCanRWHandler *fd_can_read; | |
| 2179 | - IOReadHandler *fd_read; | |
| 2693 | + IOCanRWHandler *fd_read_poll; | |
| 2694 | + IOHandler *fd_read; | |
| 2695 | + IOHandler *fd_write; | |
| 2180 | 2696 | void *opaque; |
| 2181 | 2697 | /* temporary data */ |
| 2182 | 2698 | struct pollfd *ufd; |
| 2183 | - int max_size; | |
| 2184 | 2699 | struct IOHandlerRecord *next; |
| 2185 | 2700 | } IOHandlerRecord; |
| 2186 | 2701 | |
| 2187 | 2702 | static IOHandlerRecord *first_io_handler; |
| 2188 | 2703 | |
| 2189 | -int qemu_add_fd_read_handler(int fd, IOCanRWHandler *fd_can_read, | |
| 2190 | - IOReadHandler *fd_read, void *opaque) | |
| 2704 | +/* XXX: fd_read_poll should be suppressed, but an API change is | |
| 2705 | + necessary in the character devices to suppress fd_can_read(). */ | |
| 2706 | +int qemu_set_fd_handler2(int fd, | |
| 2707 | + IOCanRWHandler *fd_read_poll, | |
| 2708 | + IOHandler *fd_read, | |
| 2709 | + IOHandler *fd_write, | |
| 2710 | + void *opaque) | |
| 2191 | 2711 | { |
| 2192 | - IOHandlerRecord *ioh; | |
| 2712 | + IOHandlerRecord **pioh, *ioh; | |
| 2193 | 2713 | |
| 2194 | - ioh = qemu_mallocz(sizeof(IOHandlerRecord)); | |
| 2195 | - if (!ioh) | |
| 2196 | - return -1; | |
| 2197 | - ioh->fd = fd; | |
| 2198 | - ioh->fd_can_read = fd_can_read; | |
| 2199 | - ioh->fd_read = fd_read; | |
| 2200 | - ioh->opaque = opaque; | |
| 2201 | - ioh->next = first_io_handler; | |
| 2202 | - first_io_handler = ioh; | |
| 2714 | + if (!fd_read && !fd_write) { | |
| 2715 | + pioh = &first_io_handler; | |
| 2716 | + for(;;) { | |
| 2717 | + ioh = *pioh; | |
| 2718 | + if (ioh == NULL) | |
| 2719 | + break; | |
| 2720 | + if (ioh->fd == fd) { | |
| 2721 | + *pioh = ioh->next; | |
| 2722 | + break; | |
| 2723 | + } | |
| 2724 | + pioh = &ioh->next; | |
| 2725 | + } | |
| 2726 | + } else { | |
| 2727 | + for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) { | |
| 2728 | + if (ioh->fd == fd) | |
| 2729 | + goto found; | |
| 2730 | + } | |
| 2731 | + ioh = qemu_mallocz(sizeof(IOHandlerRecord)); | |
| 2732 | + if (!ioh) | |
| 2733 | + return -1; | |
| 2734 | + ioh->next = first_io_handler; | |
| 2735 | + first_io_handler = ioh; | |
| 2736 | + found: | |
| 2737 | + ioh->fd = fd; | |
| 2738 | + ioh->fd_read_poll = fd_read_poll; | |
| 2739 | + ioh->fd_read = fd_read; | |
| 2740 | + ioh->fd_write = fd_write; | |
| 2741 | + ioh->opaque = opaque; | |
| 2742 | + } | |
| 2203 | 2743 | return 0; |
| 2204 | 2744 | } |
| 2205 | 2745 | |
| 2206 | -void qemu_del_fd_read_handler(int fd) | |
| 2746 | +int qemu_set_fd_handler(int fd, | |
| 2747 | + IOHandler *fd_read, | |
| 2748 | + IOHandler *fd_write, | |
| 2749 | + void *opaque) | |
| 2207 | 2750 | { |
| 2208 | - IOHandlerRecord **pioh, *ioh; | |
| 2209 | - | |
| 2210 | - pioh = &first_io_handler; | |
| 2211 | - for(;;) { | |
| 2212 | - ioh = *pioh; | |
| 2213 | - if (ioh == NULL) | |
| 2214 | - break; | |
| 2215 | - if (ioh->fd == fd) { | |
| 2216 | - *pioh = ioh->next; | |
| 2217 | - break; | |
| 2218 | - } | |
| 2219 | - pioh = &ioh->next; | |
| 2220 | - } | |
| 2751 | + return qemu_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque); | |
| 2221 | 2752 | } |
| 2222 | 2753 | |
| 2223 | 2754 | /***********************************************************/ |
| ... | ... | @@ -3080,8 +3611,6 @@ void main_loop_wait(int timeout) |
| 3080 | 3611 | #ifndef _WIN32 |
| 3081 | 3612 | struct pollfd ufds[MAX_IO_HANDLERS + 1], *pf; |
| 3082 | 3613 | IOHandlerRecord *ioh, *ioh_next; |
| 3083 | - uint8_t buf[4096]; | |
| 3084 | - int n, max_size; | |
| 3085 | 3614 | #endif |
| 3086 | 3615 | int ret; |
| 3087 | 3616 | |
| ... | ... | @@ -3093,26 +3622,18 @@ void main_loop_wait(int timeout) |
| 3093 | 3622 | /* XXX: separate device handlers from system ones */ |
| 3094 | 3623 | pf = ufds; |
| 3095 | 3624 | for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) { |
| 3096 | - if (!ioh->fd_can_read) { | |
| 3097 | - max_size = 0; | |
| 3098 | - pf->fd = ioh->fd; | |
| 3099 | - pf->events = POLLIN; | |
| 3100 | - ioh->ufd = pf; | |
| 3101 | - pf++; | |
| 3102 | - } else { | |
| 3103 | - max_size = ioh->fd_can_read(ioh->opaque); | |
| 3104 | - if (max_size > 0) { | |
| 3105 | - if (max_size > sizeof(buf)) | |
| 3106 | - max_size = sizeof(buf); | |
| 3107 | - pf->fd = ioh->fd; | |
| 3108 | - pf->events = POLLIN; | |
| 3109 | - ioh->ufd = pf; | |
| 3110 | - pf++; | |
| 3111 | - } else { | |
| 3112 | - ioh->ufd = NULL; | |
| 3113 | - } | |
| 3625 | + pf->events = 0; | |
| 3626 | + pf->fd = ioh->fd; | |
| 3627 | + if (ioh->fd_read && | |
| 3628 | + (!ioh->fd_read_poll || | |
| 3629 | + ioh->fd_read_poll(ioh->opaque) != 0)) { | |
| 3630 | + pf->events |= POLLIN; | |
| 3631 | + } | |
| 3632 | + if (ioh->fd_write) { | |
| 3633 | + pf->events |= POLLOUT; | |
| 3114 | 3634 | } |
| 3115 | - ioh->max_size = max_size; | |
| 3635 | + ioh->ufd = pf; | |
| 3636 | + pf++; | |
| 3116 | 3637 | } |
| 3117 | 3638 | |
| 3118 | 3639 | ret = poll(ufds, pf - ufds, timeout); |
| ... | ... | @@ -3121,20 +3642,11 @@ void main_loop_wait(int timeout) |
| 3121 | 3642 | for(ioh = first_io_handler; ioh != NULL; ioh = ioh_next) { |
| 3122 | 3643 | ioh_next = ioh->next; |
| 3123 | 3644 | pf = ioh->ufd; |
| 3124 | - if (pf) { | |
| 3125 | - if (pf->revents & POLLIN) { | |
| 3126 | - if (ioh->max_size == 0) { | |
| 3127 | - /* just a read event */ | |
| 3128 | - ioh->fd_read(ioh->opaque, NULL, 0); | |
| 3129 | - } else { | |
| 3130 | - n = read(ioh->fd, buf, ioh->max_size); | |
| 3131 | - if (n >= 0) { | |
| 3132 | - ioh->fd_read(ioh->opaque, buf, n); | |
| 3133 | - } else if (errno != EAGAIN) { | |
| 3134 | - ioh->fd_read(ioh->opaque, NULL, -errno); | |
| 3135 | - } | |
| 3136 | - } | |
| 3137 | - } | |
| 3645 | + if (pf->revents & POLLIN) { | |
| 3646 | + ioh->fd_read(ioh->opaque); | |
| 3647 | + } | |
| 3648 | + if (pf->revents & POLLOUT) { | |
| 3649 | + ioh->fd_write(ioh->opaque); | |
| 3138 | 3650 | } |
| 3139 | 3651 | } |
| 3140 | 3652 | } |
| ... | ... | @@ -3251,20 +3763,31 @@ void help(void) |
| 3251 | 3763 | #endif |
| 3252 | 3764 | "\n" |
| 3253 | 3765 | "Network options:\n" |
| 3254 | - "-nics n simulate 'n' network cards [default=1]\n" | |
| 3255 | - "-macaddr addr set the mac address of the first interface\n" | |
| 3256 | - "-n script set tap/tun network init script [default=%s]\n" | |
| 3257 | - "-tun-fd fd use this fd as already opened tap/tun interface\n" | |
| 3766 | + "-net nic[,vlan=n][,macaddr=addr]\n" | |
| 3767 | + " create a new Network Interface Card and connect it to VLAN 'n'\n" | |
| 3258 | 3768 | #ifdef CONFIG_SLIRP |
| 3259 | - "-user-net use user mode network stack [default if no tap/tun script]\n" | |
| 3260 | - "-tftp prefix allow tftp access to files starting with prefix [-user-net]\n" | |
| 3769 | + "-net user[,vlan=n]\n" | |
| 3770 | + " connect the user mode network stack to VLAN 'n'\n" | |
| 3771 | +#endif | |
| 3261 | 3772 | #ifndef _WIN32 |
| 3262 | - "-smb dir allow SMB access to files in 'dir' [-user-net]\n" | |
| 3773 | + "-net tap[,vlan=n][,fd=h][,ifname=name][,script=file]\n" | |
| 3774 | + " connect the host TAP network interface to VLAN 'n' and use\n" | |
| 3775 | + " the network script 'file' (default=%s);\n" | |
| 3776 | + " use 'fd=h' to connect to an already opened TAP interface\n" | |
| 3777 | + "-net socket[,vlan=n][,fd=x][,listen=[host]:port][,connect=host:port]\n" | |
| 3778 | + " connect the vlan 'n' to another VLAN using a socket connection\n" | |
| 3779 | +#endif | |
| 3780 | + "-net none use it alone to have zero network devices; if no -net option\n" | |
| 3781 | + " is provided, the default is '-net nic -net user'\n" | |
| 3782 | + "\n" | |
| 3783 | +#ifdef CONFIG_SLIRP | |
| 3784 | + "-tftp prefix allow tftp access to files starting with prefix [-net user]\n" | |
| 3785 | +#ifndef _WIN32 | |
| 3786 | + "-smb dir allow SMB access to files in 'dir' [-net user]\n" | |
| 3263 | 3787 | #endif |
| 3264 | 3788 | "-redir [tcp|udp]:host-port:[guest-host]:guest-port\n" |
| 3265 | - " redirect TCP or UDP connections from host to guest [-user-net]\n" | |
| 3789 | + " redirect TCP or UDP connections from host to guest [-net user]\n" | |
| 3266 | 3790 | #endif |
| 3267 | - "-dummy-net use dummy network stack\n" | |
| 3268 | 3791 | "\n" |
| 3269 | 3792 | "Linux boot specific:\n" |
| 3270 | 3793 | "-kernel bzImage use 'bzImage' as kernel image\n" |
| ... | ... | @@ -3308,7 +3831,9 @@ void help(void) |
| 3308 | 3831 | "qemu-fast", |
| 3309 | 3832 | #endif |
| 3310 | 3833 | DEFAULT_RAM_SIZE, |
| 3834 | +#ifndef _WIN32 | |
| 3311 | 3835 | DEFAULT_NETWORK_SCRIPT, |
| 3836 | +#endif | |
| 3312 | 3837 | DEFAULT_GDBSTUB_PORT, |
| 3313 | 3838 | "/tmp/qemu.log"); |
| 3314 | 3839 | #ifndef CONFIG_SOFTMMU |
| ... | ... | @@ -3343,15 +3868,10 @@ enum { |
| 3343 | 3868 | QEMU_OPTION_soundhw, |
| 3344 | 3869 | #endif |
| 3345 | 3870 | |
| 3346 | - QEMU_OPTION_nics, | |
| 3347 | - QEMU_OPTION_macaddr, | |
| 3348 | - QEMU_OPTION_n, | |
| 3349 | - QEMU_OPTION_tun_fd, | |
| 3350 | - QEMU_OPTION_user_net, | |
| 3871 | + QEMU_OPTION_net, | |
| 3351 | 3872 | QEMU_OPTION_tftp, |
| 3352 | 3873 | QEMU_OPTION_smb, |
| 3353 | 3874 | QEMU_OPTION_redir, |
| 3354 | - QEMU_OPTION_dummy_net, | |
| 3355 | 3875 | |
| 3356 | 3876 | QEMU_OPTION_kernel, |
| 3357 | 3877 | QEMU_OPTION_append, |
| ... | ... | @@ -3409,19 +3929,14 @@ const QEMUOption qemu_options[] = { |
| 3409 | 3929 | { "soundhw", HAS_ARG, QEMU_OPTION_soundhw }, |
| 3410 | 3930 | #endif |
| 3411 | 3931 | |
| 3412 | - { "nics", HAS_ARG, QEMU_OPTION_nics}, | |
| 3413 | - { "macaddr", HAS_ARG, QEMU_OPTION_macaddr}, | |
| 3414 | - { "n", HAS_ARG, QEMU_OPTION_n }, | |
| 3415 | - { "tun-fd", HAS_ARG, QEMU_OPTION_tun_fd }, | |
| 3932 | + { "net", HAS_ARG, QEMU_OPTION_net}, | |
| 3416 | 3933 | #ifdef CONFIG_SLIRP |
| 3417 | - { "user-net", 0, QEMU_OPTION_user_net }, | |
| 3418 | 3934 | { "tftp", HAS_ARG, QEMU_OPTION_tftp }, |
| 3419 | 3935 | #ifndef _WIN32 |
| 3420 | 3936 | { "smb", HAS_ARG, QEMU_OPTION_smb }, |
| 3421 | 3937 | #endif |
| 3422 | 3938 | { "redir", HAS_ARG, QEMU_OPTION_redir }, |
| 3423 | 3939 | #endif |
| 3424 | - { "dummy-net", 0, QEMU_OPTION_dummy_net }, | |
| 3425 | 3940 | |
| 3426 | 3941 | { "kernel", HAS_ARG, QEMU_OPTION_kernel }, |
| 3427 | 3942 | { "append", HAS_ARG, QEMU_OPTION_append }, |
| ... | ... | @@ -3596,9 +4111,7 @@ static void select_soundhw (const char *optarg) |
| 3596 | 4111 | } |
| 3597 | 4112 | #endif |
| 3598 | 4113 | |
| 3599 | -#define NET_IF_TUN 0 | |
| 3600 | -#define NET_IF_USER 1 | |
| 3601 | -#define NET_IF_DUMMY 2 | |
| 4114 | +#define MAX_NET_CLIENTS 32 | |
| 3602 | 4115 | |
| 3603 | 4116 | int main(int argc, char **argv) |
| 3604 | 4117 | { |
| ... | ... | @@ -3614,8 +4127,8 @@ int main(int argc, char **argv) |
| 3614 | 4127 | DisplayState *ds = &display_state; |
| 3615 | 4128 | int cyls, heads, secs, translation; |
| 3616 | 4129 | int start_emulation = 1; |
| 3617 | - uint8_t macaddr[6]; | |
| 3618 | - int net_if_type, nb_tun_fds, tun_fds[MAX_NICS]; | |
| 4130 | + char net_clients[MAX_NET_CLIENTS][256]; | |
| 4131 | + int nb_net_clients; | |
| 3619 | 4132 | int optind; |
| 3620 | 4133 | const char *r, *optarg; |
| 3621 | 4134 | CharDriverState *monitor_hd; |
| ... | ... | @@ -3644,7 +4157,6 @@ int main(int argc, char **argv) |
| 3644 | 4157 | ram_size = DEFAULT_RAM_SIZE * 1024 * 1024; |
| 3645 | 4158 | vga_ram_size = VGA_RAM_SIZE; |
| 3646 | 4159 | bios_size = BIOS_SIZE; |
| 3647 | - pstrcpy(network_script, sizeof(network_script), DEFAULT_NETWORK_SCRIPT); | |
| 3648 | 4160 | #ifdef CONFIG_GDBSTUB |
| 3649 | 4161 | use_gdbstub = 0; |
| 3650 | 4162 | gdbstub_port = DEFAULT_GDBSTUB_PORT; |
| ... | ... | @@ -3674,16 +4186,10 @@ int main(int argc, char **argv) |
| 3674 | 4186 | |
| 3675 | 4187 | usb_devices_index = 0; |
| 3676 | 4188 | |
| 3677 | - nb_tun_fds = 0; | |
| 3678 | - net_if_type = -1; | |
| 3679 | - nb_nics = 1; | |
| 4189 | + nb_net_clients = 0; | |
| 4190 | + | |
| 4191 | + nb_nics = 0; | |
| 3680 | 4192 | /* default mac address of the first network interface */ |
| 3681 | - macaddr[0] = 0x52; | |
| 3682 | - macaddr[1] = 0x54; | |
| 3683 | - macaddr[2] = 0x00; | |
| 3684 | - macaddr[3] = 0x12; | |
| 3685 | - macaddr[4] = 0x34; | |
| 3686 | - macaddr[5] = 0x56; | |
| 3687 | 4193 | |
| 3688 | 4194 | optind = 1; |
| 3689 | 4195 | for(;;) { |
| ... | ... | @@ -3797,21 +4303,6 @@ int main(int argc, char **argv) |
| 3797 | 4303 | case QEMU_OPTION_append: |
| 3798 | 4304 | kernel_cmdline = optarg; |
| 3799 | 4305 | break; |
| 3800 | - case QEMU_OPTION_tun_fd: | |
| 3801 | - { | |
| 3802 | - const char *p; | |
| 3803 | - int fd; | |
| 3804 | - net_if_type = NET_IF_TUN; | |
| 3805 | - if (nb_tun_fds < MAX_NICS) { | |
| 3806 | - fd = strtol(optarg, (char **)&p, 0); | |
| 3807 | - if (*p != '\0') { | |
| 3808 | - fprintf(stderr, "qemu: invalid fd for network interface %d\n", nb_tun_fds); | |
| 3809 | - exit(1); | |
| 3810 | - } | |
| 3811 | - tun_fds[nb_tun_fds++] = fd; | |
| 3812 | - } | |
| 3813 | - } | |
| 3814 | - break; | |
| 3815 | 4306 | case QEMU_OPTION_cdrom: |
| 3816 | 4307 | if (cdrom_index >= 0) { |
| 3817 | 4308 | hd_filename[cdrom_index] = optarg; |
| ... | ... | @@ -3838,33 +4329,15 @@ int main(int argc, char **argv) |
| 3838 | 4329 | case QEMU_OPTION_no_code_copy: |
| 3839 | 4330 | code_copy_enabled = 0; |
| 3840 | 4331 | break; |
| 3841 | - case QEMU_OPTION_nics: | |
| 3842 | - nb_nics = atoi(optarg); | |
| 3843 | - if (nb_nics < 0 || nb_nics > MAX_NICS) { | |
| 3844 | - fprintf(stderr, "qemu: invalid number of network interfaces\n"); | |
| 4332 | + case QEMU_OPTION_net: | |
| 4333 | + if (nb_net_clients >= MAX_NET_CLIENTS) { | |
| 4334 | + fprintf(stderr, "qemu: too many network clients\n"); | |
| 3845 | 4335 | exit(1); |
| 3846 | 4336 | } |
| 3847 | - break; | |
| 3848 | - case QEMU_OPTION_macaddr: | |
| 3849 | - { | |
| 3850 | - const char *p; | |
| 3851 | - int i; | |
| 3852 | - p = optarg; | |
| 3853 | - for(i = 0; i < 6; i++) { | |
| 3854 | - macaddr[i] = strtol(p, (char **)&p, 16); | |
| 3855 | - if (i == 5) { | |
| 3856 | - if (*p != '\0') | |
| 3857 | - goto macaddr_error; | |
| 3858 | - } else { | |
| 3859 | - if (*p != ':') { | |
| 3860 | - macaddr_error: | |
| 3861 | - fprintf(stderr, "qemu: invalid syntax for ethernet address\n"); | |
| 3862 | - exit(1); | |
| 3863 | - } | |
| 3864 | - p++; | |
| 3865 | - } | |
| 3866 | - } | |
| 3867 | - } | |
| 4337 | + pstrcpy(net_clients[nb_net_clients], | |
| 4338 | + sizeof(net_clients[0]), | |
| 4339 | + optarg); | |
| 4340 | + nb_net_clients++; | |
| 3868 | 4341 | break; |
| 3869 | 4342 | #ifdef CONFIG_SLIRP |
| 3870 | 4343 | case QEMU_OPTION_tftp: |
| ... | ... | @@ -3875,16 +4348,10 @@ int main(int argc, char **argv) |
| 3875 | 4348 | net_slirp_smb(optarg); |
| 3876 | 4349 | break; |
| 3877 | 4350 | #endif |
| 3878 | - case QEMU_OPTION_user_net: | |
| 3879 | - net_if_type = NET_IF_USER; | |
| 3880 | - break; | |
| 3881 | 4351 | case QEMU_OPTION_redir: |
| 3882 | 4352 | net_slirp_redir(optarg); |
| 3883 | 4353 | break; |
| 3884 | 4354 | #endif |
| 3885 | - case QEMU_OPTION_dummy_net: | |
| 3886 | - net_if_type = NET_IF_DUMMY; | |
| 3887 | - break; | |
| 3888 | 4355 | #ifdef HAS_AUDIO |
| 3889 | 4356 | case QEMU_OPTION_enable_audio: |
| 3890 | 4357 | audio_enabled = 1; |
| ... | ... | @@ -3930,9 +4397,6 @@ int main(int argc, char **argv) |
| 3930 | 4397 | cpu_set_log(mask); |
| 3931 | 4398 | } |
| 3932 | 4399 | break; |
| 3933 | - case QEMU_OPTION_n: | |
| 3934 | - pstrcpy(network_script, sizeof(network_script), optarg); | |
| 3935 | - break; | |
| 3936 | 4400 | #ifdef CONFIG_GDBSTUB |
| 3937 | 4401 | case QEMU_OPTION_s: |
| 3938 | 4402 | use_gdbstub = 1; |
| ... | ... | @@ -4076,48 +4540,20 @@ int main(int argc, char **argv) |
| 4076 | 4540 | #else |
| 4077 | 4541 | setvbuf(stdout, NULL, _IOLBF, 0); |
| 4078 | 4542 | #endif |
| 4079 | - | |
| 4080 | - /* init host network redirectors */ | |
| 4081 | - if (net_if_type == -1) { | |
| 4082 | - net_if_type = NET_IF_TUN; | |
| 4083 | -#if defined(CONFIG_SLIRP) | |
| 4084 | - if (access(network_script, R_OK) < 0) { | |
| 4085 | - net_if_type = NET_IF_USER; | |
| 4086 | - } | |
| 4087 | -#endif | |
| 4543 | + | |
| 4544 | + /* init network clients */ | |
| 4545 | + if (nb_net_clients == 0) { | |
| 4546 | + /* if no clients, we use a default config */ | |
| 4547 | + pstrcpy(net_clients[0], sizeof(net_clients[0]), | |
| 4548 | + "nic"); | |
| 4549 | + pstrcpy(net_clients[1], sizeof(net_clients[0]), | |
| 4550 | + "user"); | |
| 4551 | + nb_net_clients = 2; | |
| 4088 | 4552 | } |
| 4089 | 4553 | |
| 4090 | - for(i = 0; i < nb_nics; i++) { | |
| 4091 | - NetDriverState *nd = &nd_table[i]; | |
| 4092 | - nd->index = i; | |
| 4093 | - /* init virtual mac address */ | |
| 4094 | - nd->macaddr[0] = macaddr[0]; | |
| 4095 | - nd->macaddr[1] = macaddr[1]; | |
| 4096 | - nd->macaddr[2] = macaddr[2]; | |
| 4097 | - nd->macaddr[3] = macaddr[3]; | |
| 4098 | - nd->macaddr[4] = macaddr[4]; | |
| 4099 | - nd->macaddr[5] = macaddr[5] + i; | |
| 4100 | - switch(net_if_type) { | |
| 4101 | -#if defined(CONFIG_SLIRP) | |
| 4102 | - case NET_IF_USER: | |
| 4103 | - net_slirp_init(nd); | |
| 4104 | - break; | |
| 4105 | -#endif | |
| 4106 | -#if !defined(_WIN32) | |
| 4107 | - case NET_IF_TUN: | |
| 4108 | - if (i < nb_tun_fds) { | |
| 4109 | - net_fd_init(nd, tun_fds[i]); | |
| 4110 | - } else { | |
| 4111 | - if (net_tun_init(nd) < 0) | |
| 4112 | - net_dummy_init(nd); | |
| 4113 | - } | |
| 4114 | - break; | |
| 4115 | -#endif | |
| 4116 | - case NET_IF_DUMMY: | |
| 4117 | - default: | |
| 4118 | - net_dummy_init(nd); | |
| 4119 | - break; | |
| 4120 | - } | |
| 4554 | + for(i = 0;i < nb_net_clients; i++) { | |
| 4555 | + if (net_client_init(net_clients[i]) < 0) | |
| 4556 | + exit(1); | |
| 4121 | 4557 | } |
| 4122 | 4558 | |
| 4123 | 4559 | /* init the memory */ | ... | ... |
vl.h
| ... | ... | @@ -196,10 +196,17 @@ void kbd_put_keysym(int keysym); |
| 196 | 196 | |
| 197 | 197 | typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size); |
| 198 | 198 | typedef int IOCanRWHandler(void *opaque); |
| 199 | +typedef void IOHandler(void *opaque); | |
| 199 | 200 | |
| 200 | -int qemu_add_fd_read_handler(int fd, IOCanRWHandler *fd_can_read, | |
| 201 | - IOReadHandler *fd_read, void *opaque); | |
| 202 | -void qemu_del_fd_read_handler(int fd); | |
| 201 | +int qemu_set_fd_handler2(int fd, | |
| 202 | + IOCanRWHandler *fd_read_poll, | |
| 203 | + IOHandler *fd_read, | |
| 204 | + IOHandler *fd_write, | |
| 205 | + void *opaque); | |
| 206 | +int qemu_set_fd_handler(int fd, | |
| 207 | + IOHandler *fd_read, | |
| 208 | + IOHandler *fd_write, | |
| 209 | + void *opaque); | |
| 203 | 210 | |
| 204 | 211 | /* character device */ |
| 205 | 212 | |
| ... | ... | @@ -270,30 +277,42 @@ extern CharDriverState *serial_hds[MAX_SERIAL_PORTS]; |
| 270 | 277 | |
| 271 | 278 | extern CharDriverState *parallel_hds[MAX_PARALLEL_PORTS]; |
| 272 | 279 | |
| 273 | -/* network redirectors support */ | |
| 280 | +/* VLANs support */ | |
| 281 | + | |
| 282 | +typedef struct VLANClientState VLANClientState; | |
| 283 | + | |
| 284 | +struct VLANClientState { | |
| 285 | + IOReadHandler *fd_read; | |
| 286 | + void *opaque; | |
| 287 | + struct VLANClientState *next; | |
| 288 | + struct VLANState *vlan; | |
| 289 | + char info_str[256]; | |
| 290 | +}; | |
| 291 | + | |
| 292 | +typedef struct VLANState { | |
| 293 | + int id; | |
| 294 | + VLANClientState *first_client; | |
| 295 | + struct VLANState *next; | |
| 296 | +} VLANState; | |
| 297 | + | |
| 298 | +VLANState *qemu_find_vlan(int id); | |
| 299 | +VLANClientState *qemu_new_vlan_client(VLANState *vlan, | |
| 300 | + IOReadHandler *fd_read, void *opaque); | |
| 301 | +void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size); | |
| 302 | + | |
| 303 | +void do_info_network(void); | |
| 304 | + | |
| 305 | +/* NIC info */ | |
| 274 | 306 | |
| 275 | 307 | #define MAX_NICS 8 |
| 276 | 308 | |
| 277 | -typedef struct NetDriverState { | |
| 278 | - int index; /* index number in QEMU */ | |
| 309 | +typedef struct NICInfo { | |
| 279 | 310 | uint8_t macaddr[6]; |
| 280 | - char ifname[16]; | |
| 281 | - void (*send_packet)(struct NetDriverState *nd, | |
| 282 | - const uint8_t *buf, int size); | |
| 283 | - void (*add_read_packet)(struct NetDriverState *nd, | |
| 284 | - IOCanRWHandler *fd_can_read, | |
| 285 | - IOReadHandler *fd_read, void *opaque); | |
| 286 | - /* tun specific data */ | |
| 287 | - int fd; | |
| 288 | - /* slirp specific data */ | |
| 289 | -} NetDriverState; | |
| 311 | + VLANState *vlan; | |
| 312 | +} NICInfo; | |
| 290 | 313 | |
| 291 | 314 | extern int nb_nics; |
| 292 | -extern NetDriverState nd_table[MAX_NICS]; | |
| 293 | - | |
| 294 | -void qemu_send_packet(NetDriverState *nd, const uint8_t *buf, int size); | |
| 295 | -void qemu_add_read_packet(NetDriverState *nd, IOCanRWHandler *fd_can_read, | |
| 296 | - IOReadHandler *fd_read, void *opaque); | |
| 315 | +extern NICInfo nd_table[MAX_NICS]; | |
| 297 | 316 | |
| 298 | 317 | /* timers */ |
| 299 | 318 | |
| ... | ... | @@ -692,8 +711,8 @@ int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num); |
| 692 | 711 | |
| 693 | 712 | /* ne2000.c */ |
| 694 | 713 | |
| 695 | -void isa_ne2000_init(int base, int irq, NetDriverState *nd); | |
| 696 | -void pci_ne2000_init(PCIBus *bus, NetDriverState *nd); | |
| 714 | +void isa_ne2000_init(int base, int irq, NICInfo *nd); | |
| 715 | +void pci_ne2000_init(PCIBus *bus, NICInfo *nd); | |
| 697 | 716 | |
| 698 | 717 | /* pckbd.c */ |
| 699 | 718 | |
| ... | ... | @@ -781,7 +800,7 @@ void *iommu_init(uint32_t addr); |
| 781 | 800 | uint32_t iommu_translate_local(void *opaque, uint32_t addr); |
| 782 | 801 | |
| 783 | 802 | /* lance.c */ |
| 784 | -void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr); | |
| 803 | +void lance_init(NICInfo *nd, int irq, uint32_t leaddr, uint32_t ledaddr); | |
| 785 | 804 | |
| 786 | 805 | /* tcx.c */ |
| 787 | 806 | void *tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base, | ... | ... |