diff options
author | Anthony Liguori <aliguori@us.ibm.com> | 2012-08-03 13:54:05 -0500 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2012-08-03 13:54:05 -0500 |
commit | f57fb88436464cf72a2a0c7372e2dc0af1870b5f (patch) | |
tree | 9c219d95ffb1f84ae3f12a213364e80824cdc2c4 | |
parent | 3d0b7b5203fb07847bf13aee567a9c9d7483876b (diff) | |
parent | 011de2b512a83aa5e9f8899ed5bbf2f31995b90e (diff) | |
download | hqemu-f57fb88436464cf72a2a0c7372e2dc0af1870b5f.zip hqemu-f57fb88436464cf72a2a0c7372e2dc0af1870b5f.tar.gz |
Merge remote-tracking branch 'stefanha/net' into staging
* stefanha/net:
net: add the support for -netdev socket, listen
net: fix the coding style
hub: add the support for hub own flow control
net: determine if packets can be sent before net queue deliver packets
net: cleanup deliver/deliver_iov func pointers
net: Make "info network" output more readable info
net: Rename qemu_del_vlan_client() to qemu_del_net_client()
net: Rename vc local variables to nc
net: Rename VLANClientState to NetClientState
net: Rename non_vlan_clients to net_clients
net: Remove VLANState
net: Remove vlan code from net.c
net: Convert qdev_prop_vlan to peer with hub
net: Drop vlan argument to qemu_new_net_client()
hub: Check that hubs are configured correctly
net: Look up 'vlan' net clients using hubs
net: Use hubs for the vlan feature
net: Add a hub net client
net: Add interface to bridge when SIOCBRADDIF isn't available
66 files changed, 974 insertions, 827 deletions
diff --git a/hw/cadence_gem.c b/hw/cadence_gem.c index a0f51de..967f625 100644 --- a/hw/cadence_gem.c +++ b/hw/cadence_gem.c @@ -405,7 +405,7 @@ static void phy_update_link(GemState *s) } } -static int gem_can_receive(VLANClientState *nc) +static int gem_can_receive(NetClientState *nc) { GemState *s; @@ -602,7 +602,7 @@ static int gem_mac_address_filter(GemState *s, const uint8_t *packet) * gem_receive: * Fit a packet handed to us by QEMU into the receive descriptor ring. */ -static ssize_t gem_receive(VLANClientState *nc, const uint8_t *buf, size_t size) +static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size) { unsigned desc[2]; target_phys_addr_t packet_desc_addr, last_desc_addr; @@ -1146,7 +1146,7 @@ static const MemoryRegionOps gem_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static void gem_cleanup(VLANClientState *nc) +static void gem_cleanup(NetClientState *nc) { GemState *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -1154,7 +1154,7 @@ static void gem_cleanup(VLANClientState *nc) s->nic = NULL; } -static void gem_set_link(VLANClientState *nc) +static void gem_set_link(NetClientState *nc) { DB_PRINT("\n"); phy_update_link(DO_UPCAST(NICState, nc, nc)->opaque); diff --git a/hw/dp8393x.c b/hw/dp8393x.c index 756d630..4fa6ecc 100644 --- a/hw/dp8393x.c +++ b/hw/dp8393x.c @@ -673,7 +673,7 @@ static const MemoryRegionOps dp8393x_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static int nic_can_receive(VLANClientState *nc) +static int nic_can_receive(NetClientState *nc) { dp8393xState *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -722,7 +722,7 @@ static int receive_filter(dp8393xState *s, const uint8_t * buf, int size) return -1; } -static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size) +static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size) { dp8393xState *s = DO_UPCAST(NICState, nc, nc)->opaque; uint16_t data[10]; @@ -858,7 +858,7 @@ static void nic_reset(void *opaque) dp8393x_update_irq(s); } -static void nic_cleanup(VLANClientState *nc) +static void nic_cleanup(NetClientState *nc) { dp8393xState *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -899,7 +899,6 @@ void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift, s->regs[SONIC_SR] = 0x0004; /* only revision recognized by Linux */ s->conf.macaddr = nd->macaddr; - s->conf.vlan = nd->vlan; s->conf.peer = nd->netdev; s->nic = qemu_new_nic(&net_dp83932_info, &s->conf, nd->model, nd->name, s); @@ -720,7 +720,7 @@ receive_filter(E1000State *s, const uint8_t *buf, int size) } static void -e1000_set_link_status(VLANClientState *nc) +e1000_set_link_status(NetClientState *nc) { E1000State *s = DO_UPCAST(NICState, nc, nc)->opaque; uint32_t old_status = s->mac_reg[STATUS]; @@ -754,7 +754,7 @@ static bool e1000_has_rxbufs(E1000State *s, size_t total_size) } static int -e1000_can_receive(VLANClientState *nc) +e1000_can_receive(NetClientState *nc) { E1000State *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -770,7 +770,7 @@ static uint64_t rx_desc_base(E1000State *s) } static ssize_t -e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size) +e1000_receive(NetClientState *nc, const uint8_t *buf, size_t size) { E1000State *s = DO_UPCAST(NICState, nc, nc)->opaque; struct e1000_rx_desc desc; @@ -1185,7 +1185,7 @@ e1000_mmio_setup(E1000State *d) } static void -e1000_cleanup(VLANClientState *nc) +e1000_cleanup(NetClientState *nc) { E1000State *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -1201,7 +1201,7 @@ pci_e1000_uninit(PCIDevice *dev) qemu_free_timer(d->autoneg_timer); memory_region_destroy(&d->mmio); memory_region_destroy(&d->io); - qemu_del_vlan_client(&d->nic->nc); + qemu_del_net_client(&d->nic->nc); } static NetClientInfo net_e1000_info = { diff --git a/hw/eepro100.c b/hw/eepro100.c index 6b9e7f8..50d117e 100644 --- a/hw/eepro100.c +++ b/hw/eepro100.c @@ -1616,7 +1616,7 @@ static const MemoryRegionOps eepro100_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static int nic_can_receive(VLANClientState *nc) +static int nic_can_receive(NetClientState *nc) { EEPRO100State *s = DO_UPCAST(NICState, nc, nc)->opaque; TRACE(RXTX, logout("%p\n", s)); @@ -1626,7 +1626,7 @@ static int nic_can_receive(VLANClientState *nc) #endif } -static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size) +static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size) { /* TODO: * - Magic packets should set bit 30 in power management driver register. @@ -1831,7 +1831,7 @@ static const VMStateDescription vmstate_eepro100 = { } }; -static void nic_cleanup(VLANClientState *nc) +static void nic_cleanup(NetClientState *nc) { EEPRO100State *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -1847,7 +1847,7 @@ static void pci_nic_uninit(PCIDevice *pci_dev) memory_region_destroy(&s->flash_bar); vmstate_unregister(&pci_dev->qdev, s->vmstate, s); eeprom93xx_free(&pci_dev->qdev, s->eeprom); - qemu_del_vlan_client(&s->nic->nc); + qemu_del_net_client(&s->nic->nc); } static NetClientInfo net_eepro100_info = { diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c index 45fb40c..b124f5b 100644 --- a/hw/etraxfs_eth.c +++ b/hw/etraxfs_eth.c @@ -507,12 +507,12 @@ static int eth_match_groupaddr(struct fs_eth *eth, const unsigned char *sa) return match; } -static int eth_can_receive(VLANClientState *nc) +static int eth_can_receive(NetClientState *nc) { return 1; } -static ssize_t eth_receive(VLANClientState *nc, const uint8_t *buf, size_t size) +static ssize_t eth_receive(NetClientState *nc, const uint8_t *buf, size_t size) { unsigned char sa_bcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; struct fs_eth *eth = DO_UPCAST(NICState, nc, nc)->opaque; @@ -549,7 +549,7 @@ static int eth_tx_push(void *opaque, unsigned char *buf, int len, bool eop) return len; } -static void eth_set_link(VLANClientState *nc) +static void eth_set_link(NetClientState *nc) { struct fs_eth *eth = DO_UPCAST(NICState, nc, nc)->opaque; D(printf("%s %d\n", __func__, nc->link_down)); @@ -566,7 +566,7 @@ static const MemoryRegionOps eth_ops = { } }; -static void eth_cleanup(VLANClientState *nc) +static void eth_cleanup(NetClientState *nc) { struct fs_eth *eth = DO_UPCAST(NICState, nc, nc)->opaque; diff --git a/hw/exynos4_boards.c b/hw/exynos4_boards.c index e5c2a5f..4bb0a60 100644 --- a/hw/exynos4_boards.c +++ b/hw/exynos4_boards.c @@ -81,7 +81,7 @@ static void lan9215_init(uint32_t base, qemu_irq irq) SysBusDevice *s; /* This should be a 9215 but the 9118 is close enough */ - if (nd_table[0].vlan) { + if (nd_table[0].used) { qemu_check_nic_model(&nd_table[0], "lan9118"); dev = qdev_create(NULL, "lan9118"); qdev_set_nic_properties(dev, &nd_table[0]); diff --git a/hw/highbank.c b/hw/highbank.c index 4bdea5d..11aa131 100644 --- a/hw/highbank.c +++ b/hw/highbank.c @@ -284,7 +284,7 @@ static void highbank_init(ram_addr_t ram_size, sysbus_create_simple("sysbus-ahci", 0xffe08000, pic[83]); - if (nd_table[0].vlan) { + if (nd_table[0].used) { qemu_check_nic_model(&nd_table[0], "xgmac"); dev = qdev_create(NULL, "xgmac"); qdev_set_nic_properties(dev, &nd_table[0]); diff --git a/hw/integratorcp.c b/hw/integratorcp.c index deacbf4..d0e2e90 100644 --- a/hw/integratorcp.c +++ b/hw/integratorcp.c @@ -493,7 +493,7 @@ static void integratorcp_init(ram_addr_t ram_size, sysbus_create_simple("pl050_keyboard", 0x18000000, pic[3]); sysbus_create_simple("pl050_mouse", 0x19000000, pic[4]); sysbus_create_varargs("pl181", 0x1c000000, pic[23], pic[24], NULL); - if (nd_table[0].vlan) + if (nd_table[0].used) smc91c111_init(&nd_table[0], 0xc8000000, pic[27]); sysbus_create_simple("pl110", 0xc0000000, pic[22]); @@ -121,7 +121,7 @@ static void kzm_init(ram_addr_t ram_size, imx_timerp_create(0x53f98000, qdev_get_gpio_in(dev, 27), ccm); imx_timerg_create(0x53f90000, qdev_get_gpio_in(dev, 29), ccm); - if (nd_table[0].vlan) { + if (nd_table[0].used) { lan9118_init(&nd_table[0], 0xb6000000, qdev_get_gpio_in(dev, 52)); } diff --git a/hw/lan9118.c b/hw/lan9118.c index 61f1c0e..ff0a50b 100644 --- a/hw/lan9118.c +++ b/hw/lan9118.c @@ -384,7 +384,7 @@ static void phy_update_link(lan9118_state *s) phy_update_irq(s); } -static void lan9118_set_link(VLANClientState *nc) +static void lan9118_set_link(NetClientState *nc) { phy_update_link(DO_UPCAST(NICState, nc, nc)->opaque); } @@ -456,7 +456,7 @@ static void lan9118_reset(DeviceState *d) lan9118_reload_eeprom(s); } -static int lan9118_can_receive(VLANClientState *nc) +static int lan9118_can_receive(NetClientState *nc) { return 1; } @@ -509,7 +509,7 @@ static int lan9118_filter(lan9118_state *s, const uint8_t *addr) } } -static ssize_t lan9118_receive(VLANClientState *nc, const uint8_t *buf, +static ssize_t lan9118_receive(NetClientState *nc, const uint8_t *buf, size_t size) { lan9118_state *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -1304,7 +1304,7 @@ static const MemoryRegionOps lan9118_16bit_mem_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void lan9118_cleanup(VLANClientState *nc) +static void lan9118_cleanup(NetClientState *nc) { lan9118_state *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -85,7 +85,7 @@ static const MemoryRegionOps lance_mem_ops = { }, }; -static void lance_cleanup(VLANClientState *nc) +static void lance_cleanup(NetClientState *nc) { PCNetState *d = DO_UPCAST(NICState, nc, nc)->opaque; diff --git a/hw/mcf5208.c b/hw/mcf5208.c index d3ebe8d..ee25b1b 100644 --- a/hw/mcf5208.c +++ b/hw/mcf5208.c @@ -236,7 +236,7 @@ static void mcf5208evb_init(ram_addr_t ram_size, fprintf(stderr, "Too many NICs\n"); exit(1); } - if (nd_table[0].vlan) + if (nd_table[0].used) mcf_fec_init(address_space_mem, &nd_table[0], 0xfc030000, pic + 36); diff --git a/hw/mcf_fec.c b/hw/mcf_fec.c index 4ab4ff5..2fec5bc 100644 --- a/hw/mcf_fec.c +++ b/hw/mcf_fec.c @@ -351,13 +351,13 @@ static void mcf_fec_write(void *opaque, target_phys_addr_t addr, mcf_fec_update(s); } -static int mcf_fec_can_receive(VLANClientState *nc) +static int mcf_fec_can_receive(NetClientState *nc) { mcf_fec_state *s = DO_UPCAST(NICState, nc, nc)->opaque; return s->rx_enabled; } -static ssize_t mcf_fec_receive(VLANClientState *nc, const uint8_t *buf, size_t size) +static ssize_t mcf_fec_receive(NetClientState *nc, const uint8_t *buf, size_t size) { mcf_fec_state *s = DO_UPCAST(NICState, nc, nc)->opaque; mcf_fec_bd bd; @@ -439,7 +439,7 @@ static const MemoryRegionOps mcf_fec_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void mcf_fec_cleanup(VLANClientState *nc) +static void mcf_fec_cleanup(NetClientState *nc) { mcf_fec_state *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -472,7 +472,6 @@ void mcf_fec_init(MemoryRegion *sysmem, NICInfo *nd, memory_region_add_subregion(sysmem, base, &s->iomem); s->conf.macaddr = nd->macaddr; - s->conf.vlan = nd->vlan; s->conf.peer = nd->netdev; s->nic = qemu_new_nic(&net_mcf_fec_info, &s->conf, nd->model, nd->name, s); diff --git a/hw/milkymist-minimac2.c b/hw/milkymist-minimac2.c index 3924b83..b483a02 100644 --- a/hw/milkymist-minimac2.c +++ b/hw/milkymist-minimac2.c @@ -278,7 +278,7 @@ static void update_rx_interrupt(MilkymistMinimac2State *s) } } -static ssize_t minimac2_rx(VLANClientState *nc, const uint8_t *buf, size_t size) +static ssize_t minimac2_rx(NetClientState *nc, const uint8_t *buf, size_t size) { MilkymistMinimac2State *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -408,7 +408,7 @@ static const MemoryRegionOps minimac2_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static int minimac2_can_rx(VLANClientState *nc) +static int minimac2_can_rx(NetClientState *nc) { MilkymistMinimac2State *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -422,7 +422,7 @@ static int minimac2_can_rx(VLANClientState *nc) return 0; } -static void minimac2_cleanup(VLANClientState *nc) +static void minimac2_cleanup(NetClientState *nc) { MilkymistMinimac2State *s = DO_UPCAST(NICState, nc, nc)->opaque; diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c index eb03047..830f635 100644 --- a/hw/mips_mipssim.c +++ b/hw/mips_mipssim.c @@ -217,7 +217,7 @@ mips_mipssim_init (ram_addr_t ram_size, if (serial_hds[0]) serial_init(0x3f8, env->irq[4], 115200, serial_hds[0]); - if (nd_table[0].vlan) + if (nd_table[0].used) /* MIPSnet uses the MIPS CPU INT0, which is interrupt 2. */ mipsnet_init(0x4200, env->irq[2], &nd_table[0]); } diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c index d685999..967a76e 100644 --- a/hw/mips_r4k.c +++ b/hw/mips_r4k.c @@ -283,7 +283,7 @@ void mips_r4k_init (ram_addr_t ram_size, isa_vga_init(isa_bus); - if (nd_table[0].vlan) + if (nd_table[0].used) isa_ne2000_init(isa_bus, 0x300, 9, &nd_table[0]); ide_drive_get(hd, MAX_IDE_BUS); diff --git a/hw/mipsnet.c b/hw/mipsnet.c index 3385be7..28063b1 100644 --- a/hw/mipsnet.c +++ b/hw/mipsnet.c @@ -62,7 +62,7 @@ static int mipsnet_buffer_full(MIPSnetState *s) return 0; } -static int mipsnet_can_receive(VLANClientState *nc) +static int mipsnet_can_receive(NetClientState *nc) { MIPSnetState *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -71,7 +71,7 @@ static int mipsnet_can_receive(VLANClientState *nc) return !mipsnet_buffer_full(s); } -static ssize_t mipsnet_receive(VLANClientState *nc, const uint8_t *buf, size_t size) +static ssize_t mipsnet_receive(NetClientState *nc, const uint8_t *buf, size_t size) { MIPSnetState *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -209,7 +209,7 @@ static const VMStateDescription vmstate_mipsnet = { } }; -static void mipsnet_cleanup(VLANClientState *nc) +static void mipsnet_cleanup(NetClientState *nc) { MIPSnetState *s = DO_UPCAST(NICState, nc, nc)->opaque; diff --git a/hw/musicpal.c b/hw/musicpal.c index 448897f..ad725b5 100644 --- a/hw/musicpal.c +++ b/hw/musicpal.c @@ -182,12 +182,12 @@ static void eth_rx_desc_get(uint32_t addr, mv88w8618_rx_desc *desc) le32_to_cpus(&desc->next); } -static int eth_can_receive(VLANClientState *nc) +static int eth_can_receive(NetClientState *nc) { return 1; } -static ssize_t eth_receive(VLANClientState *nc, const uint8_t *buf, size_t size) +static ssize_t eth_receive(NetClientState *nc, const uint8_t *buf, size_t size) { mv88w8618_eth_state *s = DO_UPCAST(NICState, nc, nc)->opaque; uint32_t desc_addr; @@ -366,7 +366,7 @@ static const MemoryRegionOps mv88w8618_eth_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void eth_cleanup(VLANClientState *nc) +static void eth_cleanup(NetClientState *nc) { mv88w8618_eth_state *s = DO_UPCAST(NICState, nc, nc)->opaque; diff --git a/hw/ne2000-isa.c b/hw/ne2000-isa.c index 99ed965..69982a9 100644 --- a/hw/ne2000-isa.c +++ b/hw/ne2000-isa.c @@ -36,7 +36,7 @@ typedef struct ISANE2000State { NE2000State ne2000; } ISANE2000State; -static void isa_ne2000_cleanup(VLANClientState *nc) +static void isa_ne2000_cleanup(NetClientState *nc) { NE2000State *s = DO_UPCAST(NICState, nc, nc)->opaque; diff --git a/hw/ne2000.c b/hw/ne2000.c index 399d340..15605c4 100644 --- a/hw/ne2000.c +++ b/hw/ne2000.c @@ -165,7 +165,7 @@ static int ne2000_buffer_full(NE2000State *s) return 0; } -int ne2000_can_receive(VLANClientState *nc) +int ne2000_can_receive(NetClientState *nc) { NE2000State *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -176,7 +176,7 @@ int ne2000_can_receive(VLANClientState *nc) #define MIN_BUF_SIZE 60 -ssize_t ne2000_receive(VLANClientState *nc, const uint8_t *buf, size_t size_) +ssize_t ne2000_receive(NetClientState *nc, const uint8_t *buf, size_t size_) { NE2000State *s = DO_UPCAST(NICState, nc, nc)->opaque; int size = size_; @@ -703,7 +703,7 @@ void ne2000_setup_io(NE2000State *s, unsigned size) memory_region_init_io(&s->io, &ne2000_ops, s, "ne2000", size); } -static void ne2000_cleanup(VLANClientState *nc) +static void ne2000_cleanup(NetClientState *nc) { NE2000State *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -750,7 +750,7 @@ static void pci_ne2000_exit(PCIDevice *pci_dev) NE2000State *s = &d->ne2000; memory_region_destroy(&s->io); - qemu_del_vlan_client(&s->nic->nc); + qemu_del_net_client(&s->nic->nc); } static Property ne2000_properties[] = { diff --git a/hw/ne2000.h b/hw/ne2000.h index 5fee052..1e7ab07 100644 --- a/hw/ne2000.h +++ b/hw/ne2000.h @@ -31,5 +31,5 @@ typedef struct NE2000State { void ne2000_setup_io(NE2000State *s, unsigned size); extern const VMStateDescription vmstate_ne2000; void ne2000_reset(NE2000State *s); -int ne2000_can_receive(VLANClientState *vc); -ssize_t ne2000_receive(VLANClientState *vc, const uint8_t *buf, size_t size_); +int ne2000_can_receive(NetClientState *nc); +ssize_t ne2000_receive(NetClientState *nc, const uint8_t *buf, size_t size_); diff --git a/hw/opencores_eth.c b/hw/opencores_eth.c index f4498d4..8c15969 100644 --- a/hw/opencores_eth.c +++ b/hw/opencores_eth.c @@ -311,7 +311,7 @@ static void open_eth_int_source_write(OpenEthState *s, s->regs[INT_SOURCE] & s->regs[INT_MASK]); } -static void open_eth_set_link_status(VLANClientState *nc) +static void open_eth_set_link_status(NetClientState *nc) { OpenEthState *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -342,7 +342,7 @@ static void open_eth_reset(void *opaque) open_eth_set_link_status(&s->nic->nc); } -static int open_eth_can_receive(VLANClientState *nc) +static int open_eth_can_receive(NetClientState *nc) { OpenEthState *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -351,7 +351,7 @@ static int open_eth_can_receive(VLANClientState *nc) (rx_desc(s)->len_flags & RXD_E); } -static ssize_t open_eth_receive(VLANClientState *nc, +static ssize_t open_eth_receive(NetClientState *nc, const uint8_t *buf, size_t size) { OpenEthState *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -462,7 +462,7 @@ static ssize_t open_eth_receive(VLANClientState *nc, return size; } -static void open_eth_cleanup(VLANClientState *nc) +static void open_eth_cleanup(NetClientState *nc) { } diff --git a/hw/openrisc_sim.c b/hw/openrisc_sim.c index f07f7fc..55e97f0 100644 --- a/hw/openrisc_sim.c +++ b/hw/openrisc_sim.c @@ -126,7 +126,7 @@ static void openrisc_sim_init(ram_addr_t ram_size, serial_mm_init(get_system_memory(), 0x90000000, 0, cpu->env.irq[2], 115200, serial_hds[0], DEVICE_NATIVE_ENDIAN); - if (nd_table[0].vlan) { + if (nd_table[0].used) { openrisc_sim_net_init(get_system_memory(), 0x92000000, 0x92000400, cpu->env.irq[4], nd_table); } diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c index 31eb1a8..48fd447 100644 --- a/hw/pcnet-pci.c +++ b/hw/pcnet-pci.c @@ -264,7 +264,7 @@ static void pci_physical_memory_read(void *dma_opaque, target_phys_addr_t addr, pci_dma_read(dma_opaque, addr, buf, len); } -static void pci_pcnet_cleanup(VLANClientState *nc) +static void pci_pcnet_cleanup(NetClientState *nc) { PCNetState *d = DO_UPCAST(NICState, nc, nc)->opaque; @@ -279,7 +279,7 @@ static void pci_pcnet_uninit(PCIDevice *dev) memory_region_destroy(&d->io_bar); qemu_del_timer(d->state.poll_timer); qemu_free_timer(d->state.poll_timer); - qemu_del_vlan_client(&d->state.nic->nc); + qemu_del_net_client(&d->state.nic->nc); } static NetClientInfo net_pci_pcnet_info = { @@ -1004,7 +1004,7 @@ static int pcnet_tdte_poll(PCNetState *s) return !!(CSR_CXST(s) & 0x8000); } -int pcnet_can_receive(VLANClientState *nc) +int pcnet_can_receive(NetClientState *nc) { PCNetState *s = DO_UPCAST(NICState, nc, nc)->opaque; if (CSR_STOP(s) || CSR_SPND(s)) @@ -1015,7 +1015,7 @@ int pcnet_can_receive(VLANClientState *nc) #define MIN_BUF_SIZE 60 -ssize_t pcnet_receive(VLANClientState *nc, const uint8_t *buf, size_t size_) +ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_) { PCNetState *s = DO_UPCAST(NICState, nc, nc)->opaque; int is_padr = 0, is_bcast = 0, is_ladr = 0; @@ -1197,7 +1197,7 @@ ssize_t pcnet_receive(VLANClientState *nc, const uint8_t *buf, size_t size_) return size_; } -void pcnet_set_link_status(VLANClientState *nc) +void pcnet_set_link_status(NetClientState *nc) { PCNetState *d = DO_UPCAST(NICState, nc, nc)->opaque; @@ -57,9 +57,9 @@ uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr); void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val); uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr); uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap); -int pcnet_can_receive(VLANClientState *nc); -ssize_t pcnet_receive(VLANClientState *nc, const uint8_t *buf, size_t size_); -void pcnet_set_link_status(VLANClientState *nc); +int pcnet_can_receive(NetClientState *nc); +ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_); +void pcnet_set_link_status(NetClientState *nc); void pcnet_common_cleanup(PCNetState *d); int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info); extern const VMStateDescription vmstate_pcnet; diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 24b39e8..8aca0d4 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -3,6 +3,7 @@ #include "qerror.h" #include "blockdev.h" #include "hw/block-common.h" +#include "net/hub.h" void *qdev_get_prop_ptr(DeviceState *dev, Property *prop) { @@ -583,7 +584,7 @@ PropertyInfo qdev_prop_chr = { static int parse_netdev(DeviceState *dev, const char *str, void **ptr) { - VLANClientState *netdev = qemu_find_netdev(str); + NetClientState *netdev = qemu_find_netdev(str); if (netdev == NULL) { return -ENOENT; @@ -597,7 +598,7 @@ static int parse_netdev(DeviceState *dev, const char *str, void **ptr) static const char *print_netdev(void *ptr) { - VLANClientState *netdev = ptr; + NetClientState *netdev = ptr; return netdev->name ? netdev->name : ""; } @@ -624,13 +625,16 @@ PropertyInfo qdev_prop_netdev = { static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len) { - VLANState **ptr = qdev_get_prop_ptr(dev, prop); + NetClientState **ptr = qdev_get_prop_ptr(dev, prop); if (*ptr) { - return snprintf(dest, len, "%d", (*ptr)->id); - } else { - return snprintf(dest, len, "<null>"); + int id; + if (!net_hub_id_for_client(*ptr, &id)) { + return snprintf(dest, len, "%d", id); + } } + + return snprintf(dest, len, "<null>"); } static void get_vlan(Object *obj, Visitor *v, void *opaque, @@ -638,11 +642,17 @@ static void get_vlan(Object *obj, Visitor *v, void *opaque, { DeviceState *dev = DEVICE(obj); Property *prop = opaque; - VLANState **ptr = qdev_get_prop_ptr(dev, prop); - int64_t id; + NetClientState **ptr = qdev_get_prop_ptr(dev, prop); + int32_t id = -1; + + if (*ptr) { + int hub_id; + if (!net_hub_id_for_client(*ptr, &hub_id)) { + id = hub_id; + } + } - id = *ptr ? (*ptr)->id : -1; - visit_type_int64(v, &id, name, errp); + visit_type_int32(v, &id, name, errp); } static void set_vlan(Object *obj, Visitor *v, void *opaque, @@ -650,17 +660,17 @@ static void set_vlan(Object *obj, Visitor *v, void *opaque, { DeviceState *dev = DEVICE(obj); Property *prop = opaque; - VLANState **ptr = qdev_get_prop_ptr(dev, prop); + NetClientState **ptr = qdev_get_prop_ptr(dev, prop); Error *local_err = NULL; - int64_t id; - VLANState *vlan; + int32_t id; + NetClientState *hubport; if (dev->state != DEV_STATE_CREATED) { error_set(errp, QERR_PERMISSION_DENIED); return; } - visit_type_int64(v, &id, name, &local_err); + visit_type_int32(v, &id, name, &local_err); if (local_err) { error_propagate(errp, local_err); return; @@ -669,13 +679,14 @@ static void set_vlan(Object *obj, Visitor *v, void *opaque, *ptr = NULL; return; } - vlan = qemu_find_vlan(id, 1); - if (!vlan) { + + hubport = net_hub_port_find(id); + if (!hubport) { error_set(errp, QERR_INVALID_PARAMETER_VALUE, name, prop->info->name); return; } - *ptr = vlan; + *ptr = hubport; } PropertyInfo qdev_prop_vlan = { @@ -1175,7 +1186,7 @@ void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *valu assert_no_error(errp); } -void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value) +void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value) { Error *errp = NULL; assert(!value || value->name); @@ -1184,13 +1195,6 @@ void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *v assert_no_error(errp); } -void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value) -{ - Error *errp = NULL; - object_property_set_int(OBJECT(dev), value ? value->id : -1, name, &errp); - assert_no_error(errp); -} - void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value) { Error *errp = NULL; @@ -320,8 +320,6 @@ void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin) void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd) { qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a); - if (nd->vlan) - qdev_prop_set_vlan(dev, "vlan", nd->vlan); if (nd->netdev) qdev_prop_set_netdev(dev, "netdev", nd->netdev); if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED && @@ -289,9 +289,9 @@ extern PropertyInfo qdev_prop_pci_host_devaddr; #define DEFINE_PROP_STRING(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_string, char*) #define DEFINE_PROP_NETDEV(_n, _s, _f) \ - DEFINE_PROP(_n, _s, _f, qdev_prop_netdev, VLANClientState*) + DEFINE_PROP(_n, _s, _f, qdev_prop_netdev, NetClientState*) #define DEFINE_PROP_VLAN(_n, _s, _f) \ - DEFINE_PROP(_n, _s, _f, qdev_prop_vlan, VLANState*) + DEFINE_PROP(_n, _s, _f, qdev_prop_vlan, NetClientState*) #define DEFINE_PROP_DRIVE(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_drive, BlockDriverState *) #define DEFINE_PROP_MACADDR(_n, _s, _f) \ @@ -320,8 +320,7 @@ void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value); void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value); void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value); void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value); -void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value); -void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value); +void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value); int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value) QEMU_WARN_UNUSED_RESULT; void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value); void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value); diff --git a/hw/rtl8139.c b/hw/rtl8139.c index 7b78f40..844f1b8 100644 --- a/hw/rtl8139.c +++ b/hw/rtl8139.c @@ -788,7 +788,7 @@ static bool rtl8139_cp_rx_valid(RTL8139State *s) return !(s->RxRingAddrLO == 0 && s->RxRingAddrHI == 0); } -static int rtl8139_can_receive(VLANClientState *nc) +static int rtl8139_can_receive(NetClientState *nc) { RTL8139State *s = DO_UPCAST(NICState, nc, nc)->opaque; int avail; @@ -810,7 +810,7 @@ static int rtl8139_can_receive(VLANClientState *nc) } } -static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_t size_, int do_interrupt) +static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t size_, int do_interrupt) { RTL8139State *s = DO_UPCAST(NICState, nc, nc)->opaque; /* size is the length of the buffer passed to the driver */ @@ -1187,7 +1187,7 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_ return size_; } -static ssize_t rtl8139_receive(VLANClientState *nc, const uint8_t *buf, size_t size) +static ssize_t rtl8139_receive(NetClientState *nc, const uint8_t *buf, size_t size) { return rtl8139_do_receive(nc, buf, size, 1); } @@ -3431,7 +3431,7 @@ static void rtl8139_timer(void *opaque) rtl8139_set_next_tctr_time(s, qemu_get_clock_ns(vm_clock)); } -static void rtl8139_cleanup(VLANClientState *nc) +static void rtl8139_cleanup(NetClientState *nc) { RTL8139State *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -3450,7 +3450,7 @@ static void pci_rtl8139_uninit(PCIDevice *dev) } qemu_del_timer(s->timer); qemu_free_timer(s->timer); - qemu_del_vlan_client(&s->nic->nc); + qemu_del_net_client(&s->nic->nc); } static NetClientInfo net_rtl8139_info = { diff --git a/hw/smc91c111.c b/hw/smc91c111.c index 451ede0..d6ef302 100644 --- a/hw/smc91c111.c +++ b/hw/smc91c111.c @@ -628,7 +628,7 @@ static uint32_t smc91c111_readl(void *opaque, target_phys_addr_t offset) return val; } -static int smc91c111_can_receive(VLANClientState *nc) +static int smc91c111_can_receive(NetClientState *nc) { smc91c111_state *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -639,7 +639,7 @@ static int smc91c111_can_receive(VLANClientState *nc) return 1; } -static ssize_t smc91c111_receive(VLANClientState *nc, const uint8_t *buf, size_t size) +static ssize_t smc91c111_receive(NetClientState *nc, const uint8_t *buf, size_t size) { smc91c111_state *s = DO_UPCAST(NICState, nc, nc)->opaque; int status; @@ -728,7 +728,7 @@ static const MemoryRegionOps smc91c111_mem_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void smc91c111_cleanup(VLANClientState *nc) +static void smc91c111_cleanup(NetClientState *nc) { smc91c111_state *s = DO_UPCAST(NICState, nc, nc)->opaque; diff --git a/hw/spapr_llan.c b/hw/spapr_llan.c index d54f933..01e54f3 100644 --- a/hw/spapr_llan.c +++ b/hw/spapr_llan.c @@ -83,14 +83,14 @@ typedef struct VIOsPAPRVLANDevice { target_ulong rxq_ptr; } VIOsPAPRVLANDevice; -static int spapr_vlan_can_receive(VLANClientState *nc) +static int spapr_vlan_can_receive(NetClientState *nc) { VIOsPAPRVLANDevice *dev = DO_UPCAST(NICState, nc, nc)->opaque; return (dev->isopen && dev->rx_bufs > 0); } -static ssize_t spapr_vlan_receive(VLANClientState *nc, const uint8_t *buf, +static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf, size_t size) { VIOsPAPRDevice *sdev = DO_UPCAST(NICState, nc, nc)->opaque; diff --git a/hw/stellaris_enet.c b/hw/stellaris_enet.c index b593cd0..bc97280 100644 --- a/hw/stellaris_enet.c +++ b/hw/stellaris_enet.c @@ -78,7 +78,7 @@ static void stellaris_enet_update(stellaris_enet_state *s) } /* TODO: Implement MAC address filtering. */ -static ssize_t stellaris_enet_receive(VLANClientState *nc, const uint8_t *buf, size_t size) +static ssize_t stellaris_enet_receive(NetClientState *nc, const uint8_t *buf, size_t size) { stellaris_enet_state *s = DO_UPCAST(NICState, nc, nc)->opaque; int n; @@ -120,7 +120,7 @@ static ssize_t stellaris_enet_receive(VLANClientState *nc, const uint8_t *buf, s return size; } -static int stellaris_enet_can_receive(VLANClientState *nc) +static int stellaris_enet_can_receive(NetClientState *nc) { stellaris_enet_state *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -381,7 +381,7 @@ static int stellaris_enet_load(QEMUFile *f, void *opaque, int version_id) return 0; } -static void stellaris_enet_cleanup(VLANClientState *nc) +static void stellaris_enet_cleanup(NetClientState *nc) { stellaris_enet_state *s = DO_UPCAST(NICState, nc, nc)->opaque; diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index f40c349..c84892c 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -1247,7 +1247,7 @@ static int usb_net_handle_data(USBDevice *dev, USBPacket *p) return ret; } -static ssize_t usbnet_receive(VLANClientState *nc, const uint8_t *buf, size_t size) +static ssize_t usbnet_receive(NetClientState *nc, const uint8_t *buf, size_t size) { USBNetState *s = DO_UPCAST(NICState, nc, nc)->opaque; struct rndis_packet_msg_type *msg; @@ -1285,7 +1285,7 @@ static ssize_t usbnet_receive(VLANClientState *nc, const uint8_t *buf, size_t si return size; } -static int usbnet_can_receive(VLANClientState *nc) +static int usbnet_can_receive(NetClientState *nc) { USBNetState *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -1296,7 +1296,7 @@ static int usbnet_can_receive(VLANClientState *nc) return !s->in_len; } -static void usbnet_cleanup(VLANClientState *nc) +static void usbnet_cleanup(NetClientState *nc) { USBNetState *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -1309,7 +1309,7 @@ static void usb_net_handle_destroy(USBDevice *dev) /* TODO: remove the nd_table[] entry */ rndis_clear_responsequeue(s); - qemu_del_vlan_client(&s->nic->nc); + qemu_del_net_client(&s->nic->nc); } static NetClientInfo net_usbnet_info = { diff --git a/hw/vexpress.c b/hw/vexpress.c index b2dc8a5..b615844 100644 --- a/hw/vexpress.c +++ b/hw/vexpress.c @@ -427,7 +427,7 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard, memory_region_add_subregion(sysmem, map[VE_VIDEORAM], vram); /* 0x4e000000 LAN9118 Ethernet */ - if (nd_table[0].vlan) { + if (nd_table[0].used) { lan9118_init(&nd_table[0], map[VE_ETHERNET], pic[15]); } diff --git a/hw/vhost_net.c b/hw/vhost_net.c index 75f8211..ecaa22d 100644 --- a/hw/vhost_net.c +++ b/hw/vhost_net.c @@ -42,7 +42,7 @@ struct vhost_net { struct vhost_dev dev; struct vhost_virtqueue vqs[2]; int backend; - VLANClientState *vc; + NetClientState *nc; }; unsigned vhost_net_get_features(struct vhost_net *net, unsigned features) @@ -80,7 +80,7 @@ void vhost_net_ack_features(struct vhost_net *net, unsigned features) } } -static int vhost_net_get_fd(VLANClientState *backend) +static int vhost_net_get_fd(NetClientState *backend) { switch (backend->info->type) { case NET_CLIENT_OPTIONS_KIND_TAP: @@ -91,7 +91,7 @@ static int vhost_net_get_fd(VLANClientState *backend) } } -struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd, +struct vhost_net *vhost_net_init(NetClientState *backend, int devfd, bool force) { int r; @@ -104,7 +104,7 @@ struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd, if (r < 0) { goto fail; } - net->vc = backend; + net->nc = backend; net->dev.backend_features = tap_has_vnet_hdr(backend) ? 0 : (1 << VHOST_NET_F_VIRTIO_NET_HDR); net->backend = r; @@ -151,7 +151,7 @@ int vhost_net_start(struct vhost_net *net, goto fail_notifiers; } if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) { - tap_set_vnet_hdr_len(net->vc, + tap_set_vnet_hdr_len(net->nc, sizeof(struct virtio_net_hdr_mrg_rxbuf)); } @@ -160,7 +160,7 @@ int vhost_net_start(struct vhost_net *net, goto fail_start; } - net->vc->info->poll(net->vc, false); + net->nc->info->poll(net->nc, false); qemu_set_fd_handler(net->backend, NULL, NULL, NULL); file.fd = net->backend; for (file.index = 0; file.index < net->dev.nvqs; ++file.index) { @@ -177,10 +177,10 @@ fail: int r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file); assert(r >= 0); } - net->vc->info->poll(net->vc, true); + net->nc->info->poll(net->nc, true); vhost_dev_stop(&net->dev, dev); if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) { - tap_set_vnet_hdr_len(net->vc, sizeof(struct virtio_net_hdr)); + tap_set_vnet_hdr_len(net->nc, sizeof(struct virtio_net_hdr)); } fail_start: vhost_dev_disable_notifiers(&net->dev, dev); @@ -197,10 +197,10 @@ void vhost_net_stop(struct vhost_net *net, int r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file); assert(r >= 0); } - net->vc->info->poll(net->vc, true); + net->nc->info->poll(net->nc, true); vhost_dev_stop(&net->dev, dev); if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) { - tap_set_vnet_hdr_len(net->vc, sizeof(struct virtio_net_hdr)); + tap_set_vnet_hdr_len(net->nc, sizeof(struct virtio_net_hdr)); } vhost_dev_disable_notifiers(&net->dev, dev); } @@ -209,12 +209,12 @@ void vhost_net_cleanup(struct vhost_net *net) { vhost_dev_cleanup(&net->dev); if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) { - tap_set_vnet_hdr_len(net->vc, sizeof(struct virtio_net_hdr)); + tap_set_vnet_hdr_len(net->nc, sizeof(struct virtio_net_hdr)); } g_free(net); } #else -struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd, +struct vhost_net *vhost_net_init(NetClientState *backend, int devfd, bool force) { error_report("vhost-net support is not compiled in"); diff --git a/hw/vhost_net.h b/hw/vhost_net.h index 91e40b1..a9db234 100644 --- a/hw/vhost_net.h +++ b/hw/vhost_net.h @@ -6,7 +6,7 @@ struct vhost_net; typedef struct vhost_net VHostNetState; -VHostNetState *vhost_net_init(VLANClientState *backend, int devfd, bool force); +VHostNetState *vhost_net_init(NetClientState *backend, int devfd, bool force); bool vhost_net_query(VHostNetState *net, VirtIODevice *dev); int vhost_net_start(VHostNetState *net, VirtIODevice *dev); diff --git a/hw/virtio-net.c b/hw/virtio-net.c index df20499..b1998b2 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -163,7 +163,7 @@ static void virtio_net_set_status(struct VirtIODevice *vdev, uint8_t status) } } -static void virtio_net_set_link_status(VLANClientState *nc) +static void virtio_net_set_link_status(NetClientState *nc) { VirtIONet *n = DO_UPCAST(NICState, nc, nc)->opaque; uint16_t old_status = n->status; @@ -453,7 +453,7 @@ static void virtio_net_handle_rx(VirtIODevice *vdev, VirtQueue *vq) qemu_notify_event(); } -static int virtio_net_can_receive(VLANClientState *nc) +static int virtio_net_can_receive(NetClientState *nc) { VirtIONet *n = DO_UPCAST(NICState, nc, nc)->opaque; if (!n->vdev.vm_running) { @@ -593,7 +593,7 @@ static int receive_filter(VirtIONet *n, const uint8_t *buf, int size) return 0; } -static ssize_t virtio_net_receive(VLANClientState *nc, const uint8_t *buf, size_t size) +static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t size) { VirtIONet *n = DO_UPCAST(NICState, nc, nc)->opaque; struct virtio_net_hdr_mrg_rxbuf *mhdr = NULL; @@ -690,7 +690,7 @@ static ssize_t virtio_net_receive(VLANClientState *nc, const uint8_t *buf, size_ static int32_t virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq); -static void virtio_net_tx_complete(VLANClientState *nc, ssize_t len) +static void virtio_net_tx_complete(NetClientState *nc, ssize_t len) { VirtIONet *n = DO_UPCAST(NICState, nc, nc)->opaque; @@ -980,7 +980,7 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) return 0; } -static void virtio_net_cleanup(VLANClientState *nc) +static void virtio_net_cleanup(NetClientState *nc) { VirtIONet *n = DO_UPCAST(NICState, nc, nc)->opaque; @@ -1077,6 +1077,6 @@ void virtio_net_exit(VirtIODevice *vdev) qemu_bh_delete(n->tx_bh); } - qemu_del_vlan_client(&n->nic->nc); + qemu_del_net_client(&n->nic->nc); virtio_cleanup(&n->vdev); } diff --git a/hw/xen_nic.c b/hw/xen_nic.c index 593a572..8b79bfb 100644 --- a/hw/xen_nic.c +++ b/hw/xen_nic.c @@ -233,7 +233,7 @@ static void net_rx_response(struct XenNetDev *netdev, #define NET_IP_ALIGN 2 -static int net_rx_ok(VLANClientState *nc) +static int net_rx_ok(NetClientState *nc) { struct XenNetDev *netdev = DO_UPCAST(NICState, nc, nc)->opaque; RING_IDX rc, rp; @@ -254,7 +254,7 @@ static int net_rx_ok(VLANClientState *nc) return 1; } -static ssize_t net_rx_packet(VLANClientState *nc, const uint8_t *buf, size_t size) +static ssize_t net_rx_packet(NetClientState *nc, const uint8_t *buf, size_t size) { struct XenNetDev *netdev = DO_UPCAST(NICState, nc, nc)->opaque; netif_rx_request_t rxreq; @@ -325,7 +325,6 @@ static int net_init(struct XenDevice *xendev) return -1; } - netdev->conf.vlan = qemu_find_vlan(netdev->xendev.dev, 1); netdev->conf.peer = NULL; netdev->nic = qemu_new_nic(&net_xen_info, &netdev->conf, @@ -407,7 +406,7 @@ static void net_disconnect(struct XenDevice *xendev) netdev->rxs = NULL; } if (netdev->nic) { - qemu_del_vlan_client(&netdev->nic->nc); + qemu_del_net_client(&netdev->nic->nc); netdev->nic = NULL; } } @@ -308,7 +308,7 @@ static const MemoryRegionOps enet_mem_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static int eth_can_rx(VLANClientState *nc) +static int eth_can_rx(NetClientState *nc) { struct XgmacState *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -316,7 +316,7 @@ static int eth_can_rx(VLANClientState *nc) return s->regs[DMA_CONTROL] & DMA_CONTROL_SR; } -static ssize_t eth_rx(VLANClientState *nc, const uint8_t *buf, size_t size) +static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size) { struct XgmacState *s = DO_UPCAST(NICState, nc, nc)->opaque; static const unsigned char sa_bcast[6] = {0xff, 0xff, 0xff, @@ -364,7 +364,7 @@ out: return ret; } -static void eth_cleanup(VLANClientState *nc) +static void eth_cleanup(NetClientState *nc) { struct XgmacState *s = DO_UPCAST(NICState, nc, nc)->opaque; s->nic = NULL; diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c index e948505..adfaf2c 100644 --- a/hw/xilinx_axienet.c +++ b/hw/xilinx_axienet.c @@ -612,7 +612,7 @@ static const MemoryRegionOps enet_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static int eth_can_rx(VLANClientState *nc) +static int eth_can_rx(NetClientState *nc) { struct XilinxAXIEnet *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -635,7 +635,7 @@ static int enet_match_addr(const uint8_t *buf, uint32_t f0, uint32_t f1) return match; } -static ssize_t eth_rx(VLANClientState *nc, const uint8_t *buf, size_t size) +static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size) { struct XilinxAXIEnet *s = DO_UPCAST(NICState, nc, nc)->opaque; static const unsigned char sa_bcast[6] = {0xff, 0xff, 0xff, @@ -780,7 +780,7 @@ static ssize_t eth_rx(VLANClientState *nc, const uint8_t *buf, size_t size) return size; } -static void eth_cleanup(VLANClientState *nc) +static void eth_cleanup(NetClientState *nc) { /* FIXME. */ struct XilinxAXIEnet *s = DO_UPCAST(NICState, nc, nc)->opaque; diff --git a/hw/xilinx_ethlite.c b/hw/xilinx_ethlite.c index 9006322..56ca620 100644 --- a/hw/xilinx_ethlite.c +++ b/hw/xilinx_ethlite.c @@ -160,7 +160,7 @@ static const MemoryRegionOps eth_ops = { } }; -static int eth_can_rx(VLANClientState *nc) +static int eth_can_rx(NetClientState *nc) { struct xlx_ethlite *s = DO_UPCAST(NICState, nc, nc)->opaque; int r; @@ -168,7 +168,7 @@ static int eth_can_rx(VLANClientState *nc) return r; } -static ssize_t eth_rx(VLANClientState *nc, const uint8_t *buf, size_t size) +static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size) { struct xlx_ethlite *s = DO_UPCAST(NICState, nc, nc)->opaque; unsigned int rxbase = s->rxbuf * (0x800 / 4); @@ -194,7 +194,7 @@ static ssize_t eth_rx(VLANClientState *nc, const uint8_t *buf, size_t size) return size; } -static void eth_cleanup(VLANClientState *nc) +static void eth_cleanup(NetClientState *nc) { struct xlx_ethlite *s = DO_UPCAST(NICState, nc, nc)->opaque; diff --git a/hw/xtensa_lx60.c b/hw/xtensa_lx60.c index 152eed9..c4f616f 100644 --- a/hw/xtensa_lx60.c +++ b/hw/xtensa_lx60.c @@ -201,7 +201,7 @@ static void lx_init(const LxBoardDesc *board, memory_region_init(system_io, "lx60.io", 224 * 1024 * 1024); memory_region_add_subregion(system_memory, 0xf0000000, system_io); lx60_fpga_init(system_io, 0x0d020000); - if (nd_table[0].vlan) { + if (nd_table[0].used) { lx60_net_init(system_io, 0x0d030000, 0x0d030400, 0x0d800000, xtensa_get_extint(env, 1), nd_table); } @@ -30,6 +30,7 @@ #include "net/dump.h" #include "net/slirp.h" #include "net/vde.h" +#include "net/hub.h" #include "net/util.h" #include "monitor.h" #include "qemu-common.h" @@ -46,8 +47,7 @@ # define CONFIG_NET_BRIDGE #endif -static QTAILQ_HEAD(, VLANState) vlans; -static QTAILQ_HEAD(, VLANClientState) non_vlan_clients; +static QTAILQ_HEAD(, NetClientState) net_clients; int default_net = 1; @@ -132,11 +132,11 @@ int parse_host_port(struct sockaddr_in *saddr, const char *str) return 0; } -void qemu_format_nic_info_str(VLANClientState *vc, uint8_t macaddr[6]) +void qemu_format_nic_info_str(NetClientState *nc, uint8_t macaddr[6]) { - snprintf(vc->info_str, sizeof(vc->info_str), + snprintf(nc->info_str, sizeof(nc->info_str), "model=%s,macaddr=%02x:%02x:%02x:%02x:%02x:%02x", - vc->model, + nc->model, macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]); } @@ -156,23 +156,25 @@ void qemu_macaddr_default_if_unset(MACAddr *macaddr) macaddr->a[5] = 0x56 + index++; } -static char *assign_name(VLANClientState *vc1, const char *model) +/** + * Generate a name for net client + * + * Only net clients created with the legacy -net option need this. Naming is + * mandatory for net clients created with -netdev. + */ +static char *assign_name(NetClientState *nc1, const char *model) { - VLANState *vlan; - VLANClientState *vc; + NetClientState *nc; char buf[256]; int id = 0; - QTAILQ_FOREACH(vlan, &vlans, next) { - QTAILQ_FOREACH(vc, &vlan->clients, next) { - if (vc != vc1 && strcmp(vc->model, model) == 0) { - id++; - } + QTAILQ_FOREACH(nc, &net_clients, next) { + if (nc == nc1) { + continue; } - } - - QTAILQ_FOREACH(vc, &non_vlan_clients, next) { - if (vc != vc1 && strcmp(vc->model, model) == 0) { + /* For compatibility only bump id for net clients on a vlan */ + if (strcmp(nc->model, model) == 0 && + net_hub_id_for_client(nc, NULL) == 0) { id++; } } @@ -182,55 +184,35 @@ static char *assign_name(VLANClientState *vc1, const char *model) return g_strdup(buf); } -static ssize_t qemu_deliver_packet(VLANClientState *sender, - unsigned flags, - const uint8_t *data, - size_t size, - void *opaque); -static ssize_t qemu_deliver_packet_iov(VLANClientState *sender, - unsigned flags, - const struct iovec *iov, - int iovcnt, - void *opaque); - -VLANClientState *qemu_new_net_client(NetClientInfo *info, - VLANState *vlan, - VLANClientState *peer, - const char *model, - const char *name) +NetClientState *qemu_new_net_client(NetClientInfo *info, + NetClientState *peer, + const char *model, + const char *name) { - VLANClientState *vc; + NetClientState *nc; - assert(info->size >= sizeof(VLANClientState)); + assert(info->size >= sizeof(NetClientState)); - vc = g_malloc0(info->size); + nc = g_malloc0(info->size); - vc->info = info; - vc->model = g_strdup(model); + nc->info = info; + nc->model = g_strdup(model); if (name) { - vc->name = g_strdup(name); + nc->name = g_strdup(name); } else { - vc->name = assign_name(vc, model); + nc->name = assign_name(nc, model); } - if (vlan) { - assert(!peer); - vc->vlan = vlan; - QTAILQ_INSERT_TAIL(&vc->vlan->clients, vc, next); - } else { - if (peer) { - assert(!peer->peer); - vc->peer = peer; - peer->peer = vc; - } - QTAILQ_INSERT_TAIL(&non_vlan_clients, vc, next); - - vc->send_queue = qemu_new_net_queue(qemu_deliver_packet, - qemu_deliver_packet_iov, - vc); + if (peer) { + assert(!peer->peer); + nc->peer = peer; + peer->peer = nc; } + QTAILQ_INSERT_TAIL(&net_clients, nc, next); + + nc->send_queue = qemu_new_net_queue(nc); - return vc; + return nc; } NICState *qemu_new_nic(NetClientInfo *info, @@ -239,13 +221,13 @@ NICState *qemu_new_nic(NetClientInfo *info, const char *name, void *opaque) { - VLANClientState *nc; + NetClientState *nc; NICState *nic; assert(info->type == NET_CLIENT_OPTIONS_KIND_NIC); assert(info->size >= sizeof(NICState)); - nc = qemu_new_net_client(info, conf->vlan, conf->peer, model, name); + nc = qemu_new_net_client(info, conf->peer, model, name); nic = DO_UPCAST(NICState, nc, nc); nic->conf = conf; @@ -254,250 +236,131 @@ NICState *qemu_new_nic(NetClientInfo *info, return nic; } -static void qemu_cleanup_vlan_client(VLANClientState *vc) +static void qemu_cleanup_net_client(NetClientState *nc) { - if (vc->vlan) { - QTAILQ_REMOVE(&vc->vlan->clients, vc, next); - } else { - QTAILQ_REMOVE(&non_vlan_clients, vc, next); - } + QTAILQ_REMOVE(&net_clients, nc, next); - if (vc->info->cleanup) { - vc->info->cleanup(vc); + if (nc->info->cleanup) { + nc->info->cleanup(nc); } } -static void qemu_free_vlan_client(VLANClientState *vc) +static void qemu_free_net_client(NetClientState *nc) { - if (!vc->vlan) { - if (vc->send_queue) { - qemu_del_net_queue(vc->send_queue); - } - if (vc->peer) { - vc->peer->peer = NULL; - } + if (nc->send_queue) { + qemu_del_net_queue(nc->send_queue); } - g_free(vc->name); - g_free(vc->model); - g_free(vc); + if (nc->peer) { + nc->peer->peer = NULL; + } + g_free(nc->name); + g_free(nc->model); + g_free(nc); } -void qemu_del_vlan_client(VLANClientState *vc) +void qemu_del_net_client(NetClientState *nc) { /* If there is a peer NIC, delete and cleanup client, but do not free. */ - if (!vc->vlan && vc->peer && vc->peer->info->type == NET_CLIENT_OPTIONS_KIND_NIC) { - NICState *nic = DO_UPCAST(NICState, nc, vc->peer); + if (nc->peer && nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_NIC) { + NICState *nic = DO_UPCAST(NICState, nc, nc->peer); if (nic->peer_deleted) { return; } nic->peer_deleted = true; /* Let NIC know peer is gone. */ - vc->peer->link_down = true; - if (vc->peer->info->link_status_changed) { - vc->peer->info->link_status_changed(vc->peer); + nc->peer->link_down = true; + if (nc->peer->info->link_status_changed) { + nc->peer->info->link_status_changed(nc->peer); } - qemu_cleanup_vlan_client(vc); + qemu_cleanup_net_client(nc); return; } /* If this is a peer NIC and peer has already been deleted, free it now. */ - if (!vc->vlan && vc->peer && vc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) { - NICState *nic = DO_UPCAST(NICState, nc, vc); + if (nc->peer && nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) { + NICState *nic = DO_UPCAST(NICState, nc, nc); if (nic->peer_deleted) { - qemu_free_vlan_client(vc->peer); + qemu_free_net_client(nc->peer); } } - qemu_cleanup_vlan_client(vc); - qemu_free_vlan_client(vc); -} - -VLANClientState * -qemu_find_vlan_client_by_name(Monitor *mon, int vlan_id, - const char *client_str) -{ - VLANState *vlan; - VLANClientState *vc; - - vlan = qemu_find_vlan(vlan_id, 0); - if (!vlan) { - monitor_printf(mon, "unknown VLAN %d\n", vlan_id); - return NULL; - } - - QTAILQ_FOREACH(vc, &vlan->clients, next) { - if (!strcmp(vc->name, client_str)) { - break; - } - } - if (!vc) { - monitor_printf(mon, "can't find device %s on VLAN %d\n", - client_str, vlan_id); - } - - return vc; + qemu_cleanup_net_client(nc); + qemu_free_net_client(nc); } void qemu_foreach_nic(qemu_nic_foreach func, void *opaque) { - VLANClientState *nc; - VLANState *vlan; + NetClientState *nc; - QTAILQ_FOREACH(nc, &non_vlan_clients, next) { + QTAILQ_FOREACH(nc, &net_clients, next) { if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) { func(DO_UPCAST(NICState, nc, nc), opaque); } } - - QTAILQ_FOREACH(vlan, &vlans, next) { - QTAILQ_FOREACH(nc, &vlan->clients, next) { - if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) { - func(DO_UPCAST(NICState, nc, nc), opaque); - } - } - } } -int qemu_can_send_packet(VLANClientState *sender) +int qemu_can_send_packet(NetClientState *sender) { - VLANState *vlan = sender->vlan; - VLANClientState *vc; - - if (sender->peer) { - if (sender->peer->receive_disabled) { - return 0; - } else if (sender->peer->info->can_receive && - !sender->peer->info->can_receive(sender->peer)) { - return 0; - } else { - return 1; - } - } - - if (!sender->vlan) { + if (!sender->peer) { return 1; } - QTAILQ_FOREACH(vc, &vlan->clients, next) { - if (vc == sender) { - continue; - } - - /* no can_receive() handler, they can always receive */ - if (vc->info->can_receive && !vc->info->can_receive(vc)) { - return 0; - } + if (sender->peer->receive_disabled) { + return 0; + } else if (sender->peer->info->can_receive && + !sender->peer->info->can_receive(sender->peer)) { + return 0; } return 1; } -static ssize_t qemu_deliver_packet(VLANClientState *sender, - unsigned flags, - const uint8_t *data, - size_t size, - void *opaque) +ssize_t qemu_deliver_packet(NetClientState *sender, + unsigned flags, + const uint8_t *data, + size_t size, + void *opaque) { - VLANClientState *vc = opaque; + NetClientState *nc = opaque; ssize_t ret; - if (vc->link_down) { + if (nc->link_down) { return size; } - if (vc->receive_disabled) { + if (nc->receive_disabled) { return 0; } - if (flags & QEMU_NET_PACKET_FLAG_RAW && vc->info->receive_raw) { - ret = vc->info->receive_raw(vc, data, size); + if (flags & QEMU_NET_PACKET_FLAG_RAW && nc->info->receive_raw) { + ret = nc->info->receive_raw(nc, data, size); } else { - ret = vc->info->receive(vc, data, size); + ret = nc->info->receive(nc, data, size); } if (ret == 0) { - vc->receive_disabled = 1; + nc->receive_disabled = 1; }; return ret; } -static ssize_t qemu_vlan_deliver_packet(VLANClientState *sender, - unsigned flags, - const uint8_t *buf, - size_t size, - void *opaque) -{ - VLANState *vlan = opaque; - VLANClientState *vc; - ssize_t ret = -1; - - QTAILQ_FOREACH(vc, &vlan->clients, next) { - ssize_t len; - - if (vc == sender) { - continue; - } - - if (vc->link_down) { - ret = size; - continue; - } - - if (vc->receive_disabled) { - ret = 0; - continue; - } - - if (flags & QEMU_NET_PACKET_FLAG_RAW && vc->info->receive_raw) { - len = vc->info->receive_raw(vc, buf, size); - } else { - len = vc->info->receive(vc, buf, size); - } - - if (len == 0) { - vc->receive_disabled = 1; - } - - ret = (ret >= 0) ? ret : len; - - } - - return ret; -} - -void qemu_purge_queued_packets(VLANClientState *vc) +void qemu_purge_queued_packets(NetClientState *nc) { - NetQueue *queue; - - if (!vc->peer && !vc->vlan) { + if (!nc->peer) { return; } - if (vc->peer) { - queue = vc->peer->send_queue; - } else { - queue = vc->vlan->send_queue; - } - - qemu_net_queue_purge(queue, vc); + qemu_net_queue_purge(nc->peer->send_queue, nc); } -void qemu_flush_queued_packets(VLANClientState *vc) +void qemu_flush_queued_packets(NetClientState *nc) { - NetQueue *queue; - - vc->receive_disabled = 0; - - if (vc->vlan) { - queue = vc->vlan->send_queue; - } else { - queue = vc->send_queue; - } + nc->receive_disabled = 0; - qemu_net_queue_flush(queue); + qemu_net_queue_flush(nc->send_queue); } -static ssize_t qemu_send_packet_async_with_flags(VLANClientState *sender, +static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender, unsigned flags, const uint8_t *buf, int size, NetPacketSent *sent_cb) @@ -509,20 +372,16 @@ static ssize_t qemu_send_packet_async_with_flags(VLANClientState *sender, hex_dump(stdout, buf, size); #endif - if (sender->link_down || (!sender->peer && !sender->vlan)) { + if (sender->link_down || !sender->peer) { return size; } - if (sender->peer) { - queue = sender->peer->send_queue; - } else { - queue = sender->vlan->send_queue; - } + queue = sender->peer->send_queue; return qemu_net_queue_send(queue, sender, flags, buf, size, sent_cb); } -ssize_t qemu_send_packet_async(VLANClientState *sender, +ssize_t qemu_send_packet_async(NetClientState *sender, const uint8_t *buf, int size, NetPacketSent *sent_cb) { @@ -530,18 +389,18 @@ ssize_t qemu_send_packet_async(VLANClientState *sender, buf, size, sent_cb); } -void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size) +void qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size) { - qemu_send_packet_async(vc, buf, size, NULL); + qemu_send_packet_async(nc, buf, size, NULL); } -ssize_t qemu_send_packet_raw(VLANClientState *vc, const uint8_t *buf, int size) +ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size) { - return qemu_send_packet_async_with_flags(vc, QEMU_NET_PACKET_FLAG_RAW, + return qemu_send_packet_async_with_flags(nc, QEMU_NET_PACKET_FLAG_RAW, buf, size, NULL); } -static ssize_t vc_sendv_compat(VLANClientState *vc, const struct iovec *iov, +static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov, int iovcnt) { uint8_t buffer[4096]; @@ -549,79 +408,39 @@ static ssize_t vc_sendv_compat(VLANClientState *vc, const struct iovec *iov, offset = iov_to_buf(iov, iovcnt, 0, buffer, sizeof(buffer)); - return vc->info->receive(vc, buffer, offset); + return nc->info->receive(nc, buffer, offset); } -static ssize_t qemu_deliver_packet_iov(VLANClientState *sender, - unsigned flags, - const struct iovec *iov, - int iovcnt, - void *opaque) +ssize_t qemu_deliver_packet_iov(NetClientState *sender, + unsigned flags, + const struct iovec *iov, + int iovcnt, + void *opaque) { - VLANClientState *vc = opaque; + NetClientState *nc = opaque; - if (vc->link_down) { + if (nc->link_down) { return iov_size(iov, iovcnt); } - if (vc->info->receive_iov) { - return vc->info->receive_iov(vc, iov, iovcnt); + if (nc->info->receive_iov) { + return nc->info->receive_iov(nc, iov, iovcnt); } else { - return vc_sendv_compat(vc, iov, iovcnt); + return nc_sendv_compat(nc, iov, iovcnt); } } -static ssize_t qemu_vlan_deliver_packet_iov(VLANClientState *sender, - unsigned flags, - const struct iovec *iov, - int iovcnt, - void *opaque) -{ - VLANState *vlan = opaque; - VLANClientState *vc; - ssize_t ret = -1; - - QTAILQ_FOREACH(vc, &vlan->clients, next) { - ssize_t len; - - if (vc == sender) { - continue; - } - - if (vc->link_down) { - ret = iov_size(iov, iovcnt); - continue; - } - - assert(!(flags & QEMU_NET_PACKET_FLAG_RAW)); - - if (vc->info->receive_iov) { - len = vc->info->receive_iov(vc, iov, iovcnt); - } else { - len = vc_sendv_compat(vc, iov, iovcnt); - } - - ret = (ret >= 0) ? ret : len; - } - - return ret; -} - -ssize_t qemu_sendv_packet_async(VLANClientState *sender, +ssize_t qemu_sendv_packet_async(NetClientState *sender, const struct iovec *iov, int iovcnt, NetPacketSent *sent_cb) { NetQueue *queue; - if (sender->link_down || (!sender->peer && !sender->vlan)) { + if (sender->link_down || !sender->peer) { return iov_size(iov, iovcnt); } - if (sender->peer) { - queue = sender->peer->send_queue; - } else { - queue = sender->vlan->send_queue; - } + queue = sender->peer->send_queue; return qemu_net_queue_send_iov(queue, sender, QEMU_NET_PACKET_FLAG_NONE, @@ -629,48 +448,20 @@ ssize_t qemu_sendv_packet_async(VLANClientState *sender, } ssize_t -qemu_sendv_packet(VLANClientState *vc, const struct iovec *iov, int iovcnt) +qemu_sendv_packet(NetClientState *nc, const struct iovec *iov, int iovcnt) { - return qemu_sendv_packet_async(vc, iov, iovcnt, NULL); -} - -/* find or alloc a new VLAN */ -VLANState *qemu_find_vlan(int id, int allocate) -{ - VLANState *vlan; - - QTAILQ_FOREACH(vlan, &vlans, next) { - if (vlan->id == id) { - return vlan; - } - } - - if (!allocate) { - return NULL; - } - - vlan = g_malloc0(sizeof(VLANState)); - vlan->id = id; - QTAILQ_INIT(&vlan->clients); - - vlan->send_queue = qemu_new_net_queue(qemu_vlan_deliver_packet, - qemu_vlan_deliver_packet_iov, - vlan); - - QTAILQ_INSERT_TAIL(&vlans, vlan, next); - - return vlan; + return qemu_sendv_packet_async(nc, iov, iovcnt, NULL); } -VLANClientState *qemu_find_netdev(const char *id) +NetClientState *qemu_find_netdev(const char *id) { - VLANClientState *vc; + NetClientState *nc; - QTAILQ_FOREACH(vc, &non_vlan_clients, next) { - if (vc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) + QTAILQ_FOREACH(nc, &net_clients, next) { + if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) continue; - if (!strcmp(vc->name, id)) { - return vc; + if (!strcmp(nc->name, id)) { + return nc; } } @@ -750,7 +541,7 @@ int net_handle_fd_param(Monitor *mon, const char *param) } static int net_init_nic(const NetClientOptions *opts, const char *name, - VLANState *vlan) + NetClientState *peer) { int idx; NICInfo *nd; @@ -776,8 +567,8 @@ static int net_init_nic(const NetClientOptions *opts, const char *name, return -1; } } else { - assert(vlan); - nd->vlan = vlan; + assert(peer); + nd->netdev = peer; } if (name) { nd->name = g_strdup(name); @@ -816,20 +607,21 @@ static int net_init_nic(const NetClientOptions *opts, const char *name, static int (* const net_client_init_fun[NET_CLIENT_OPTIONS_KIND_MAX])( const NetClientOptions *opts, const char *name, - VLANState *vlan) = { - [NET_CLIENT_OPTIONS_KIND_NIC] = net_init_nic, + NetClientState *peer) = { + [NET_CLIENT_OPTIONS_KIND_NIC] = net_init_nic, #ifdef CONFIG_SLIRP - [NET_CLIENT_OPTIONS_KIND_USER] = net_init_slirp, + [NET_CLIENT_OPTIONS_KIND_USER] = net_init_slirp, #endif - [NET_CLIENT_OPTIONS_KIND_TAP] = net_init_tap, - [NET_CLIENT_OPTIONS_KIND_SOCKET] = net_init_socket, + [NET_CLIENT_OPTIONS_KIND_TAP] = net_init_tap, + [NET_CLIENT_OPTIONS_KIND_SOCKET] = net_init_socket, #ifdef CONFIG_VDE - [NET_CLIENT_OPTIONS_KIND_VDE] = net_init_vde, + [NET_CLIENT_OPTIONS_KIND_VDE] = net_init_vde, #endif - [NET_CLIENT_OPTIONS_KIND_DUMP] = net_init_dump, + [NET_CLIENT_OPTIONS_KIND_DUMP] = net_init_dump, #ifdef CONFIG_NET_BRIDGE - [NET_CLIENT_OPTIONS_KIND_BRIDGE] = net_init_bridge, + [NET_CLIENT_OPTIONS_KIND_BRIDGE] = net_init_bridge, #endif + [NET_CLIENT_OPTIONS_KIND_HUBPORT] = net_init_hubport, }; @@ -859,6 +651,7 @@ static int net_client_init1(const void *object, int is_netdev, Error **errp) #ifdef CONFIG_NET_BRIDGE case NET_CLIENT_OPTIONS_KIND_BRIDGE: #endif + case NET_CLIENT_OPTIONS_KIND_HUBPORT: break; default: @@ -874,17 +667,17 @@ static int net_client_init1(const void *object, int is_netdev, Error **errp) } if (net_client_init_fun[opts->kind]) { - VLANState *vlan = NULL; + NetClientState *peer = NULL; /* Do not add to a vlan if it's a -netdev or a nic with a netdev= * parameter. */ if (!is_netdev && (opts->kind != NET_CLIENT_OPTIONS_KIND_NIC || !opts->nic->has_netdev)) { - vlan = qemu_find_vlan(u.net->has_vlan ? u.net->vlan : 0, true); + peer = net_hub_add_port(u.net->has_vlan ? u.net->vlan : 0, NULL); } - if (net_client_init_fun[opts->kind](opts, name, vlan) < 0) { + if (net_client_init_fun[opts->kind](opts, name, peer) < 0) { /* TODO push error reporting into init() methods */ error_set(errp, QERR_DEVICE_INIT_FAILED, NetClientOptionsKind_lookup[opts->kind]); @@ -986,19 +779,19 @@ void net_host_device_add(Monitor *mon, const QDict *qdict) void net_host_device_remove(Monitor *mon, const QDict *qdict) { - VLANClientState *vc; + NetClientState *nc; int vlan_id = qdict_get_int(qdict, "vlan_id"); const char *device = qdict_get_str(qdict, "device"); - vc = qemu_find_vlan_client_by_name(mon, vlan_id, device); - if (!vc) { + nc = net_hub_find_client_by_name(vlan_id, device); + if (!nc) { return; } - if (!net_host_check_device(vc->model)) { + if (!net_host_check_device(nc->model)) { monitor_printf(mon, "invalid host network device %s\n", device); return; } - qemu_del_vlan_client(vc); + qemu_del_net_client(nc); } void netdev_add(QemuOpts *opts, Error **errp) @@ -1038,48 +831,45 @@ exit_err: void qmp_netdev_del(const char *id, Error **errp) { - VLANClientState *vc; + NetClientState *nc; - vc = qemu_find_netdev(id); - if (!vc) { + nc = qemu_find_netdev(id); + if (!nc) { error_set(errp, QERR_DEVICE_NOT_FOUND, id); return; } - qemu_del_vlan_client(vc); + qemu_del_net_client(nc); qemu_opts_del(qemu_opts_find(qemu_find_opts_err("netdev", errp), id)); } -static void print_net_client(Monitor *mon, VLANClientState *vc) +void print_net_client(Monitor *mon, NetClientState *nc) { - monitor_printf(mon, "%s: type=%s,%s\n", vc->name, - NetClientOptionsKind_lookup[vc->info->type], vc->info_str); + monitor_printf(mon, "%s: type=%s,%s\n", nc->name, + NetClientOptionsKind_lookup[nc->info->type], nc->info_str); } void do_info_network(Monitor *mon) { - VLANState *vlan; - VLANClientState *vc, *peer; + NetClientState *nc, *peer; NetClientOptionsKind type; - QTAILQ_FOREACH(vlan, &vlans, next) { - monitor_printf(mon, "VLAN %d devices:\n", vlan->id); + net_hub_info(mon); + + QTAILQ_FOREACH(nc, &net_clients, next) { + peer = nc->peer; + type = nc->info->type; - QTAILQ_FOREACH(vc, &vlan->clients, next) { - monitor_printf(mon, " "); - print_net_client(mon, vc); + /* Skip if already printed in hub info */ + if (net_hub_id_for_client(nc, NULL) == 0) { + continue; } - } - monitor_printf(mon, "Devices not on any VLAN:\n"); - QTAILQ_FOREACH(vc, &non_vlan_clients, next) { - peer = vc->peer; - type = vc->info->type; + if (!peer || type == NET_CLIENT_OPTIONS_KIND_NIC) { - monitor_printf(mon, " "); - print_net_client(mon, vc); + print_net_client(mon, nc); } /* else it's a netdev connected to a NIC, printed with the NIC */ if (peer && type == NET_CLIENT_OPTIONS_KIND_NIC) { - monitor_printf(mon, " \\ "); + monitor_printf(mon, " \\ "); print_net_client(mon, peer); } } @@ -1087,32 +877,23 @@ void do_info_network(Monitor *mon) void qmp_set_link(const char *name, bool up, Error **errp) { - VLANState *vlan; - VLANClientState *vc = NULL; + NetClientState *nc = NULL; - QTAILQ_FOREACH(vlan, &vlans, next) { - QTAILQ_FOREACH(vc, &vlan->clients, next) { - if (strcmp(vc->name, name) == 0) { - goto done; - } - } - } - QTAILQ_FOREACH(vc, &non_vlan_clients, next) { - if (!strcmp(vc->name, name)) { + QTAILQ_FOREACH(nc, &net_clients, next) { + if (!strcmp(nc->name, name)) { goto done; } } done: - - if (!vc) { + if (!nc) { error_set(errp, QERR_DEVICE_NOT_FOUND, name); return; } - vc->link_down = !up; + nc->link_down = !up; - if (vc->info->link_status_changed) { - vc->info->link_status_changed(vc); + if (nc->info->link_status_changed) { + nc->info->link_status_changed(nc); } /* Notify peer. Don't update peer link status: this makes it possible to @@ -1122,31 +903,23 @@ done: * Current behaviour is compatible with qemu vlans where there could be * multiple clients that can still communicate with each other in * disconnected mode. For now maintain this compatibility. */ - if (vc->peer && vc->peer->info->link_status_changed) { - vc->peer->info->link_status_changed(vc->peer); + if (nc->peer && nc->peer->info->link_status_changed) { + nc->peer->info->link_status_changed(nc->peer); } } void net_cleanup(void) { - VLANState *vlan; - VLANClientState *vc, *next_vc; - - QTAILQ_FOREACH(vlan, &vlans, next) { - QTAILQ_FOREACH_SAFE(vc, &vlan->clients, next, next_vc) { - qemu_del_vlan_client(vc); - } - } + NetClientState *nc, *next_vc; - QTAILQ_FOREACH_SAFE(vc, &non_vlan_clients, next, next_vc) { - qemu_del_vlan_client(vc); + QTAILQ_FOREACH_SAFE(nc, &net_clients, next, next_vc) { + qemu_del_net_client(nc); } } void net_check_clients(void) { - VLANState *vlan; - VLANClientState *vc; + NetClientState *nc; int i; /* Don't warn about the default network setup that you get if @@ -1161,35 +934,13 @@ void net_check_clients(void) return; } - QTAILQ_FOREACH(vlan, &vlans, next) { - int has_nic = 0, has_host_dev = 0; - - QTAILQ_FOREACH(vc, &vlan->clients, next) { - switch (vc->info->type) { - case NET_CLIENT_OPTIONS_KIND_NIC: - has_nic = 1; - break; - case NET_CLIENT_OPTIONS_KIND_USER: - case NET_CLIENT_OPTIONS_KIND_TAP: - case NET_CLIENT_OPTIONS_KIND_SOCKET: - case NET_CLIENT_OPTIONS_KIND_VDE: - has_host_dev = 1; - break; - default: ; - } - } - if (has_host_dev && !has_nic) - fprintf(stderr, "Warning: vlan %d with no nics\n", vlan->id); - if (has_nic && !has_host_dev) - fprintf(stderr, - "Warning: vlan %d is not connected to host network\n", - vlan->id); - } - QTAILQ_FOREACH(vc, &non_vlan_clients, next) { - if (!vc->peer) { + net_hub_check_clients(); + + QTAILQ_FOREACH(nc, &net_clients, next) { + if (!nc->peer) { fprintf(stderr, "Warning: %s %s has no peer\n", - vc->info->type == NET_CLIENT_OPTIONS_KIND_NIC ? "nic" : "netdev", - vc->name); + nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC ? + "nic" : "netdev", nc->name); } } @@ -1249,8 +1000,7 @@ int net_init_clients(void) #endif } - QTAILQ_INIT(&vlans); - QTAILQ_INIT(&non_vlan_clients); + QTAILQ_INIT(&net_clients); if (qemu_opts_foreach(qemu_find_opts("netdev"), net_init_netdev, NULL, 1) == -1) return -1; @@ -17,25 +17,24 @@ struct MACAddr { typedef struct NICConf { MACAddr macaddr; - VLANState *vlan; - VLANClientState *peer; + NetClientState *peer; int32_t bootindex; } NICConf; #define DEFINE_NIC_PROPERTIES(_state, _conf) \ DEFINE_PROP_MACADDR("mac", _state, _conf.macaddr), \ - DEFINE_PROP_VLAN("vlan", _state, _conf.vlan), \ + DEFINE_PROP_VLAN("vlan", _state, _conf.peer), \ DEFINE_PROP_NETDEV("netdev", _state, _conf.peer), \ DEFINE_PROP_INT32("bootindex", _state, _conf.bootindex, -1) -/* VLANs support */ +/* Net clients */ -typedef void (NetPoll)(VLANClientState *, bool enable); -typedef int (NetCanReceive)(VLANClientState *); -typedef ssize_t (NetReceive)(VLANClientState *, const uint8_t *, size_t); -typedef ssize_t (NetReceiveIOV)(VLANClientState *, const struct iovec *, int); -typedef void (NetCleanup) (VLANClientState *); -typedef void (LinkStatusChanged)(VLANClientState *); +typedef void (NetPoll)(NetClientState *, bool enable); +typedef int (NetCanReceive)(NetClientState *); +typedef ssize_t (NetReceive)(NetClientState *, const uint8_t *, size_t); +typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int); +typedef void (NetCleanup) (NetClientState *); +typedef void (LinkStatusChanged)(NetClientState *); typedef struct NetClientInfo { NetClientOptionsKind type; @@ -49,12 +48,11 @@ typedef struct NetClientInfo { NetPoll *poll; } NetClientInfo; -struct VLANClientState { +struct NetClientState { NetClientInfo *info; int link_down; - QTAILQ_ENTRY(VLANClientState) next; - struct VLANState *vlan; - VLANClientState *peer; + QTAILQ_ENTRY(NetClientState) next; + NetClientState *peer; NetQueue *send_queue; char *model; char *name; @@ -63,54 +61,57 @@ struct VLANClientState { }; typedef struct NICState { - VLANClientState nc; + NetClientState nc; NICConf *conf; void *opaque; bool peer_deleted; } NICState; -struct VLANState { - int id; - QTAILQ_HEAD(, VLANClientState) clients; - QTAILQ_ENTRY(VLANState) next; - NetQueue *send_queue; -}; - -VLANState *qemu_find_vlan(int id, int allocate); -VLANClientState *qemu_find_netdev(const char *id); -VLANClientState *qemu_new_net_client(NetClientInfo *info, - VLANState *vlan, - VLANClientState *peer, - const char *model, - const char *name); +NetClientState *qemu_find_netdev(const char *id); +NetClientState *qemu_new_net_client(NetClientInfo *info, + NetClientState *peer, + const char *model, + const char *name); NICState *qemu_new_nic(NetClientInfo *info, NICConf *conf, const char *model, const char *name, void *opaque); -void qemu_del_vlan_client(VLANClientState *vc); -VLANClientState *qemu_find_vlan_client_by_name(Monitor *mon, int vlan_id, - const char *client_str); +void qemu_del_net_client(NetClientState *nc); +NetClientState *qemu_find_vlan_client_by_name(Monitor *mon, int vlan_id, + const char *client_str); typedef void (*qemu_nic_foreach)(NICState *nic, void *opaque); void qemu_foreach_nic(qemu_nic_foreach func, void *opaque); -int qemu_can_send_packet(VLANClientState *vc); -ssize_t qemu_sendv_packet(VLANClientState *vc, const struct iovec *iov, +int qemu_can_send_packet(NetClientState *nc); +ssize_t qemu_sendv_packet(NetClientState *nc, const struct iovec *iov, int iovcnt); -ssize_t qemu_sendv_packet_async(VLANClientState *vc, const struct iovec *iov, +ssize_t qemu_sendv_packet_async(NetClientState *nc, const struct iovec *iov, int iovcnt, NetPacketSent *sent_cb); -void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size); -ssize_t qemu_send_packet_raw(VLANClientState *vc, const uint8_t *buf, int size); -ssize_t qemu_send_packet_async(VLANClientState *vc, const uint8_t *buf, +void qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size); +ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size); +ssize_t qemu_send_packet_async(NetClientState *nc, const uint8_t *buf, int size, NetPacketSent *sent_cb); -void qemu_purge_queued_packets(VLANClientState *vc); -void qemu_flush_queued_packets(VLANClientState *vc); -void qemu_format_nic_info_str(VLANClientState *vc, uint8_t macaddr[6]); +void qemu_purge_queued_packets(NetClientState *nc); +void qemu_flush_queued_packets(NetClientState *nc); +void qemu_format_nic_info_str(NetClientState *nc, uint8_t macaddr[6]); void qemu_macaddr_default_if_unset(MACAddr *macaddr); int qemu_show_nic_models(const char *arg, const char *const *models); void qemu_check_nic_model(NICInfo *nd, const char *model); int qemu_find_nic_model(NICInfo *nd, const char * const *models, const char *default_model); +ssize_t qemu_deliver_packet(NetClientState *sender, + unsigned flags, + const uint8_t *data, + size_t size, + void *opaque); +ssize_t qemu_deliver_packet_iov(NetClientState *sender, + unsigned flags, + const struct iovec *iov, + int iovcnt, + void *opaque); + +void print_net_client(Monitor *mon, NetClientState *nc); void do_info_network(Monitor *mon); /* NIC info */ @@ -122,8 +123,7 @@ struct NICInfo { char *model; char *name; char *devaddr; - VLANState *vlan; - VLANClientState *netdev; + NetClientState *netdev; int used; /* is this slot in nd_table[] being used? */ int instantiated; /* does this NICInfo correspond to an instantiated NIC? */ int nvectors; diff --git a/net/Makefile.objs b/net/Makefile.objs index 72f50bc..cf04187 100644 --- a/net/Makefile.objs +++ b/net/Makefile.objs @@ -1,4 +1,4 @@ -common-obj-y = queue.o checksum.o util.o +common-obj-y = queue.o checksum.o util.o hub.o common-obj-y += socket.o common-obj-y += dump.o common-obj-$(CONFIG_POSIX) += tap.o @@ -27,9 +27,10 @@ #include "qemu-error.h" #include "qemu-log.h" #include "qemu-timer.h" +#include "hub.h" typedef struct DumpState { - VLANClientState nc; + NetClientState nc; int64_t start_ts; int fd; int pcap_caplen; @@ -56,7 +57,7 @@ struct pcap_sf_pkthdr { uint32_t len; }; -static ssize_t dump_receive(VLANClientState *nc, const uint8_t *buf, size_t size) +static ssize_t dump_receive(NetClientState *nc, const uint8_t *buf, size_t size) { DumpState *s = DO_UPCAST(DumpState, nc, nc); struct pcap_sf_pkthdr hdr; @@ -85,7 +86,7 @@ static ssize_t dump_receive(VLANClientState *nc, const uint8_t *buf, size_t size return size; } -static void dump_cleanup(VLANClientState *nc) +static void dump_cleanup(NetClientState *nc) { DumpState *s = DO_UPCAST(DumpState, nc, nc); @@ -99,11 +100,11 @@ static NetClientInfo net_dump_info = { .cleanup = dump_cleanup, }; -static int net_dump_init(VLANState *vlan, const char *device, +static int net_dump_init(NetClientState *peer, const char *device, const char *name, const char *filename, int len) { struct pcap_file_hdr hdr; - VLANClientState *nc; + NetClientState *nc; DumpState *s; struct tm tm; int fd; @@ -128,7 +129,7 @@ static int net_dump_init(VLANState *vlan, const char *device, return -1; } - nc = qemu_new_net_client(&net_dump_info, vlan, NULL, device, name); + nc = qemu_new_net_client(&net_dump_info, peer, device, name); snprintf(nc->info_str, sizeof(nc->info_str), "dump to %s (len=%d)", filename, len); @@ -145,7 +146,7 @@ static int net_dump_init(VLANState *vlan, const char *device, } int net_init_dump(const NetClientOptions *opts, const char *name, - VLANState *vlan) + NetClientState *peer) { int len; const char *file; @@ -155,12 +156,18 @@ int net_init_dump(const NetClientOptions *opts, const char *name, assert(opts->kind == NET_CLIENT_OPTIONS_KIND_DUMP); dump = opts->dump; - assert(vlan); + assert(peer); if (dump->has_file) { file = dump->file; } else { - snprintf(def_file, sizeof(def_file), "qemu-vlan%d.pcap", vlan->id); + int id; + int ret; + + ret = net_hub_id_for_client(peer, &id); + assert(ret == 0); /* peer must be on a hub */ + + snprintf(def_file, sizeof(def_file), "qemu-vlan%d.pcap", id); file = def_file; } @@ -174,5 +181,5 @@ int net_init_dump(const NetClientOptions *opts, const char *name, len = 65536; } - return net_dump_init(vlan, "dump", name, file, len); + return net_dump_init(peer, "dump", name, file, len); } @@ -28,6 +28,6 @@ #include "qapi-types.h" int net_init_dump(const NetClientOptions *opts, const char *name, - VLANState *vlan); + NetClientState *peer); #endif /* QEMU_NET_DUMP_H */ diff --git a/net/hub.c b/net/hub.c new file mode 100644 index 0000000..ac157e3 --- /dev/null +++ b/net/hub.c @@ -0,0 +1,339 @@ +/* + * Hub net client + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> + * Zhi Yong Wu <wuzhy@linux.vnet.ibm.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#include "monitor.h" +#include "net.h" +#include "hub.h" +#include "iov.h" + +/* + * A hub broadcasts incoming packets to all its ports except the source port. + * Hubs can be used to provide independent network segments, also confusingly + * named the QEMU 'vlan' feature. + */ + +typedef struct NetHub NetHub; + +typedef struct NetHubPort { + NetClientState nc; + QLIST_ENTRY(NetHubPort) next; + NetHub *hub; + int id; +} NetHubPort; + +struct NetHub { + int id; + QLIST_ENTRY(NetHub) next; + int num_ports; + QLIST_HEAD(, NetHubPort) ports; +}; + +static QLIST_HEAD(, NetHub) hubs = QLIST_HEAD_INITIALIZER(&hubs); + +static ssize_t net_hub_receive(NetHub *hub, NetHubPort *source_port, + const uint8_t *buf, size_t len) +{ + NetHubPort *port; + + QLIST_FOREACH(port, &hub->ports, next) { + if (port == source_port) { + continue; + } + + qemu_send_packet(&port->nc, buf, len); + } + return len; +} + +static ssize_t net_hub_receive_iov(NetHub *hub, NetHubPort *source_port, + const struct iovec *iov, int iovcnt) +{ + NetHubPort *port; + ssize_t len = iov_size(iov, iovcnt); + + QLIST_FOREACH(port, &hub->ports, next) { + if (port == source_port) { + continue; + } + + qemu_sendv_packet(&port->nc, iov, iovcnt); + } + return len; +} + +static NetHub *net_hub_new(int id) +{ + NetHub *hub; + + hub = g_malloc(sizeof(*hub)); + hub->id = id; + hub->num_ports = 0; + QLIST_INIT(&hub->ports); + + QLIST_INSERT_HEAD(&hubs, hub, next); + + return hub; +} + +static int net_hub_port_can_receive(NetClientState *nc) +{ + NetHubPort *port; + NetHubPort *src_port = DO_UPCAST(NetHubPort, nc, nc); + NetHub *hub = src_port->hub; + + QLIST_FOREACH(port, &hub->ports, next) { + if (port == src_port) { + continue; + } + + if (!qemu_can_send_packet(&port->nc)) { + return 0; + } + } + + return 1; +} + +static ssize_t net_hub_port_receive(NetClientState *nc, + const uint8_t *buf, size_t len) +{ + NetHubPort *port = DO_UPCAST(NetHubPort, nc, nc); + + return net_hub_receive(port->hub, port, buf, len); +} + +static ssize_t net_hub_port_receive_iov(NetClientState *nc, + const struct iovec *iov, int iovcnt) +{ + NetHubPort *port = DO_UPCAST(NetHubPort, nc, nc); + + return net_hub_receive_iov(port->hub, port, iov, iovcnt); +} + +static void net_hub_port_cleanup(NetClientState *nc) +{ + NetHubPort *port = DO_UPCAST(NetHubPort, nc, nc); + + QLIST_REMOVE(port, next); +} + +static NetClientInfo net_hub_port_info = { + .type = NET_CLIENT_OPTIONS_KIND_HUBPORT, + .size = sizeof(NetHubPort), + .can_receive = net_hub_port_can_receive, + .receive = net_hub_port_receive, + .receive_iov = net_hub_port_receive_iov, + .cleanup = net_hub_port_cleanup, +}; + +static NetHubPort *net_hub_port_new(NetHub *hub, const char *name) +{ + NetClientState *nc; + NetHubPort *port; + int id = hub->num_ports++; + char default_name[128]; + + if (!name) { + snprintf(default_name, sizeof(default_name), + "hub%dport%d", hub->id, id); + name = default_name; + } + + nc = qemu_new_net_client(&net_hub_port_info, NULL, "hub", name); + port = DO_UPCAST(NetHubPort, nc, nc); + port->id = id; + port->hub = hub; + + QLIST_INSERT_HEAD(&hub->ports, port, next); + + return port; +} + +/** + * Create a port on a given hub + * @name: Net client name or NULL for default name. + * + * If there is no existing hub with the given id then a new hub is created. + */ +NetClientState *net_hub_add_port(int hub_id, const char *name) +{ + NetHub *hub; + NetHubPort *port; + + QLIST_FOREACH(hub, &hubs, next) { + if (hub->id == hub_id) { + break; + } + } + + if (!hub) { + hub = net_hub_new(hub_id); + } + + port = net_hub_port_new(hub, name); + return &port->nc; +} + +/** + * Find a specific client on a hub + */ +NetClientState *net_hub_find_client_by_name(int hub_id, const char *name) +{ + NetHub *hub; + NetHubPort *port; + NetClientState *peer; + + QLIST_FOREACH(hub, &hubs, next) { + if (hub->id == hub_id) { + QLIST_FOREACH(port, &hub->ports, next) { + peer = port->nc.peer; + + if (peer && strcmp(peer->name, name) == 0) { + return peer; + } + } + } + } + return NULL; +} + +/** + * Find a available port on a hub; otherwise create one new port + */ +NetClientState *net_hub_port_find(int hub_id) +{ + NetHub *hub; + NetHubPort *port; + NetClientState *nc; + + QLIST_FOREACH(hub, &hubs, next) { + if (hub->id == hub_id) { + QLIST_FOREACH(port, &hub->ports, next) { + nc = port->nc.peer; + if (!nc) { + return &(port->nc); + } + } + break; + } + } + + nc = net_hub_add_port(hub_id, NULL); + return nc; +} + +/** + * Print hub configuration + */ +void net_hub_info(Monitor *mon) +{ + NetHub *hub; + NetHubPort *port; + + QLIST_FOREACH(hub, &hubs, next) { + monitor_printf(mon, "hub %d\n", hub->id); + QLIST_FOREACH(port, &hub->ports, next) { + if (port->nc.peer) { + monitor_printf(mon, " \\ "); + print_net_client(mon, port->nc.peer); + } + } + } +} + +/** + * Get the hub id that a client is connected to + * + * @id Pointer for hub id output, may be NULL + */ +int net_hub_id_for_client(NetClientState *nc, int *id) +{ + NetHubPort *port; + + if (nc->info->type == NET_CLIENT_OPTIONS_KIND_HUBPORT) { + port = DO_UPCAST(NetHubPort, nc, nc); + } else if (nc->peer != NULL && nc->peer->info->type == + NET_CLIENT_OPTIONS_KIND_HUBPORT) { + port = DO_UPCAST(NetHubPort, nc, nc->peer); + } else { + return -ENOENT; + } + + if (id) { + *id = port->hub->id; + } + return 0; +} + +int net_init_hubport(const NetClientOptions *opts, const char *name, + NetClientState *peer) +{ + const NetdevHubPortOptions *hubport; + + assert(opts->kind == NET_CLIENT_OPTIONS_KIND_HUBPORT); + hubport = opts->hubport; + + /* Treat hub port like a backend, NIC must be the one to peer */ + if (peer) { + return -EINVAL; + } + + net_hub_add_port(hubport->hubid, name); + return 0; +} + +/** + * Warn if hub configurations are likely wrong + */ +void net_hub_check_clients(void) +{ + NetHub *hub; + NetHubPort *port; + NetClientState *peer; + + QLIST_FOREACH(hub, &hubs, next) { + int has_nic = 0, has_host_dev = 0; + + QLIST_FOREACH(port, &hub->ports, next) { + peer = port->nc.peer; + if (!peer) { + fprintf(stderr, "Warning: hub port %s has no peer\n", + port->nc.name); + continue; + } + + switch (peer->info->type) { + case NET_CLIENT_OPTIONS_KIND_NIC: + has_nic = 1; + break; + case NET_CLIENT_OPTIONS_KIND_USER: + case NET_CLIENT_OPTIONS_KIND_TAP: + case NET_CLIENT_OPTIONS_KIND_SOCKET: + case NET_CLIENT_OPTIONS_KIND_VDE: + has_host_dev = 1; + break; + default: + break; + } + } + if (has_host_dev && !has_nic) { + fprintf(stderr, "Warning: vlan %d with no nics\n", hub->id); + } + if (has_nic && !has_host_dev) { + fprintf(stderr, + "Warning: vlan %d is not connected to host network\n", + hub->id); + } + } +} diff --git a/net/hub.h b/net/hub.h new file mode 100644 index 0000000..26a1ade --- /dev/null +++ b/net/hub.h @@ -0,0 +1,29 @@ +/* + * Hub net client + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> + * Zhi Yong Wu <wuzhy@linux.vnet.ibm.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#ifndef NET_HUB_H +#define NET_HUB_H + +#include "qemu-common.h" + +int net_init_hubport(const NetClientOptions *opts, const char *name, + NetClientState *peer); +NetClientState *net_hub_add_port(int hub_id, const char *name); +NetClientState *net_hub_find_client_by_name(int hub_id, const char *name); +void net_hub_info(Monitor *mon); +int net_hub_id_for_client(NetClientState *nc, int *id); +void net_hub_check_clients(void); +NetClientState *net_hub_port_find(int hub_id); + +#endif /* NET_HUB_H */ diff --git a/net/queue.c b/net/queue.c index 1ab5247..e8030aa 100644 --- a/net/queue.c +++ b/net/queue.c @@ -23,6 +23,7 @@ #include "net/queue.h" #include "qemu-queue.h" +#include "net.h" /* The delivery handler may only return zero if it will call * qemu_net_queue_flush() when it determines that it is once again able @@ -40,7 +41,7 @@ struct NetPacket { QTAILQ_ENTRY(NetPacket) entry; - VLANClientState *sender; + NetClientState *sender; unsigned flags; int size; NetPacketSent *sent_cb; @@ -48,8 +49,6 @@ struct NetPacket { }; struct NetQueue { - NetPacketDeliver *deliver; - NetPacketDeliverIOV *deliver_iov; void *opaque; QTAILQ_HEAD(packets, NetPacket) packets; @@ -57,16 +56,12 @@ struct NetQueue { unsigned delivering : 1; }; -NetQueue *qemu_new_net_queue(NetPacketDeliver *deliver, - NetPacketDeliverIOV *deliver_iov, - void *opaque) +NetQueue *qemu_new_net_queue(void *opaque) { NetQueue *queue; queue = g_malloc0(sizeof(NetQueue)); - queue->deliver = deliver; - queue->deliver_iov = deliver_iov; queue->opaque = opaque; QTAILQ_INIT(&queue->packets); @@ -89,7 +84,7 @@ void qemu_del_net_queue(NetQueue *queue) } static ssize_t qemu_net_queue_append(NetQueue *queue, - VLANClientState *sender, + NetClientState *sender, unsigned flags, const uint8_t *buf, size_t size, @@ -110,7 +105,7 @@ static ssize_t qemu_net_queue_append(NetQueue *queue, } static ssize_t qemu_net_queue_append_iov(NetQueue *queue, - VLANClientState *sender, + NetClientState *sender, unsigned flags, const struct iovec *iov, int iovcnt, @@ -143,7 +138,7 @@ static ssize_t qemu_net_queue_append_iov(NetQueue *queue, } static ssize_t qemu_net_queue_deliver(NetQueue *queue, - VLANClientState *sender, + NetClientState *sender, unsigned flags, const uint8_t *data, size_t size) @@ -151,14 +146,14 @@ static ssize_t qemu_net_queue_deliver(NetQueue *queue, ssize_t ret = -1; queue->delivering = 1; - ret = queue->deliver(sender, flags, data, size, queue->opaque); + ret = qemu_deliver_packet(sender, flags, data, size, queue->opaque); queue->delivering = 0; return ret; } static ssize_t qemu_net_queue_deliver_iov(NetQueue *queue, - VLANClientState *sender, + NetClientState *sender, unsigned flags, const struct iovec *iov, int iovcnt) @@ -166,14 +161,14 @@ static ssize_t qemu_net_queue_deliver_iov(NetQueue *queue, ssize_t ret = -1; queue->delivering = 1; - ret = queue->deliver_iov(sender, flags, iov, iovcnt, queue->opaque); + ret = qemu_deliver_packet_iov(sender, flags, iov, iovcnt, queue->opaque); queue->delivering = 0; return ret; } ssize_t qemu_net_queue_send(NetQueue *queue, - VLANClientState *sender, + NetClientState *sender, unsigned flags, const uint8_t *data, size_t size, @@ -181,8 +176,8 @@ ssize_t qemu_net_queue_send(NetQueue *queue, { ssize_t ret; - if (queue->delivering) { - return qemu_net_queue_append(queue, sender, flags, data, size, NULL); + if (queue->delivering || !qemu_can_send_packet(sender)) { + return qemu_net_queue_append(queue, sender, flags, data, size, sent_cb); } ret = qemu_net_queue_deliver(queue, sender, flags, data, size); @@ -197,7 +192,7 @@ ssize_t qemu_net_queue_send(NetQueue *queue, } ssize_t qemu_net_queue_send_iov(NetQueue *queue, - VLANClientState *sender, + NetClientState *sender, unsigned flags, const struct iovec *iov, int iovcnt, @@ -205,8 +200,9 @@ ssize_t qemu_net_queue_send_iov(NetQueue *queue, { ssize_t ret; - if (queue->delivering) { - return qemu_net_queue_append_iov(queue, sender, flags, iov, iovcnt, NULL); + if (queue->delivering || !qemu_can_send_packet(sender)) { + return qemu_net_queue_append_iov(queue, sender, flags, + iov, iovcnt, sent_cb); } ret = qemu_net_queue_deliver_iov(queue, sender, flags, iov, iovcnt); @@ -220,7 +216,7 @@ ssize_t qemu_net_queue_send_iov(NetQueue *queue, return ret; } -void qemu_net_queue_purge(NetQueue *queue, VLANClientState *from) +void qemu_net_queue_purge(NetQueue *queue, NetClientState *from) { NetPacket *packet, *next; diff --git a/net/queue.h b/net/queue.h index a31958e..9d44a9b 100644 --- a/net/queue.h +++ b/net/queue.h @@ -29,43 +29,30 @@ typedef struct NetPacket NetPacket; typedef struct NetQueue NetQueue; -typedef void (NetPacketSent) (VLANClientState *sender, ssize_t ret); - -typedef ssize_t (NetPacketDeliver) (VLANClientState *sender, - unsigned flags, - const uint8_t *buf, - size_t size, - void *opaque); - -typedef ssize_t (NetPacketDeliverIOV) (VLANClientState *sender, - unsigned flags, - const struct iovec *iov, - int iovcnt, - void *opaque); +typedef void (NetPacketSent) (NetClientState *sender, ssize_t ret); #define QEMU_NET_PACKET_FLAG_NONE 0 #define QEMU_NET_PACKET_FLAG_RAW (1<<0) -NetQueue *qemu_new_net_queue(NetPacketDeliver *deliver, - NetPacketDeliverIOV *deliver_iov, - void *opaque); +NetQueue *qemu_new_net_queue(void *opaque); + void qemu_del_net_queue(NetQueue *queue); ssize_t qemu_net_queue_send(NetQueue *queue, - VLANClientState *sender, + NetClientState *sender, unsigned flags, const uint8_t *data, size_t size, NetPacketSent *sent_cb); ssize_t qemu_net_queue_send_iov(NetQueue *queue, - VLANClientState *sender, + NetClientState *sender, unsigned flags, const struct iovec *iov, int iovcnt, NetPacketSent *sent_cb); -void qemu_net_queue_purge(NetQueue *queue, VLANClientState *from); +void qemu_net_queue_purge(NetQueue *queue, NetClientState *from); void qemu_net_queue_flush(NetQueue *queue); #endif /* QEMU_NET_QUEUE_H */ diff --git a/net/slirp.c b/net/slirp.c index 5c2e6b2..08adb97 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -30,6 +30,7 @@ #include <sys/wait.h> #endif #include "net.h" +#include "net/hub.h" #include "monitor.h" #include "qemu_socket.h" #include "slirp/libslirp.h" @@ -67,7 +68,7 @@ struct slirp_config_str { }; typedef struct SlirpState { - VLANClientState nc; + NetClientState nc; QTAILQ_ENTRY(SlirpState) entry; Slirp *slirp; #ifndef _WIN32 @@ -96,13 +97,6 @@ static void slirp_smb_cleanup(SlirpState *s); static inline void slirp_smb_cleanup(SlirpState *s) { } #endif -int slirp_can_output(void *opaque) -{ - SlirpState *s = opaque; - - return qemu_can_send_packet(&s->nc); -} - void slirp_output(void *opaque, const uint8_t *pkt, int pkt_len) { SlirpState *s = opaque; @@ -110,7 +104,7 @@ void slirp_output(void *opaque, const uint8_t *pkt, int pkt_len) qemu_send_packet(&s->nc, pkt, pkt_len); } -static ssize_t net_slirp_receive(VLANClientState *nc, const uint8_t *buf, size_t size) +static ssize_t net_slirp_receive(NetClientState *nc, const uint8_t *buf, size_t size) { SlirpState *s = DO_UPCAST(SlirpState, nc, nc); @@ -119,7 +113,7 @@ static ssize_t net_slirp_receive(VLANClientState *nc, const uint8_t *buf, size_t return size; } -static void net_slirp_cleanup(VLANClientState *nc) +static void net_slirp_cleanup(NetClientState *nc) { SlirpState *s = DO_UPCAST(SlirpState, nc, nc); @@ -135,7 +129,7 @@ static NetClientInfo net_slirp_info = { .cleanup = net_slirp_cleanup, }; -static int net_slirp_init(VLANState *vlan, const char *model, +static int net_slirp_init(NetClientState *peer, const char *model, const char *name, int restricted, const char *vnetwork, const char *vhost, const char *vhostname, const char *tftp_export, @@ -152,7 +146,7 @@ static int net_slirp_init(VLANState *vlan, const char *model, #ifndef _WIN32 struct in_addr smbsrv = { .s_addr = 0 }; #endif - VLANClientState *nc; + NetClientState *nc; SlirpState *s; char buf[20]; uint32_t addr; @@ -238,7 +232,7 @@ static int net_slirp_init(VLANState *vlan, const char *model, } #endif - nc = qemu_new_net_client(&net_slirp_info, vlan, NULL, model, name); + nc = qemu_new_net_client(&net_slirp_info, peer, model, name); snprintf(nc->info_str, sizeof(nc->info_str), "net=%s,restrict=%s", inet_ntoa(net), @@ -274,7 +268,7 @@ static int net_slirp_init(VLANState *vlan, const char *model, return 0; error: - qemu_del_vlan_client(nc); + qemu_del_net_client(nc); return -1; } @@ -283,8 +277,8 @@ static SlirpState *slirp_lookup(Monitor *mon, const char *vlan, { if (vlan) { - VLANClientState *nc; - nc = qemu_find_vlan_client_by_name(mon, strtol(vlan, NULL, 0), stack); + NetClientState *nc; + nc = net_hub_find_client_by_name(strtol(vlan, NULL, 0), stack); if (!nc) { return NULL; } @@ -679,8 +673,10 @@ void do_info_usernet(Monitor *mon) SlirpState *s; QTAILQ_FOREACH(s, &slirp_stacks, entry) { + int id; + bool got_vlan_id = net_hub_id_for_client(&s->nc, &id) == 0; monitor_printf(mon, "VLAN %d (%s):\n", - s->nc.vlan ? s->nc.vlan->id : -1, + got_vlan_id ? id : -1, s->nc.name); slirp_connection_info(s->slirp, mon); } @@ -703,7 +699,7 @@ net_init_slirp_configs(const StringList *fwd, int flags) } int net_init_slirp(const NetClientOptions *opts, const char *name, - VLANState *vlan) + NetClientState *peer) { struct slirp_config_str *config; char *vnet; @@ -722,7 +718,7 @@ int net_init_slirp(const NetClientOptions *opts, const char *name, net_init_slirp_configs(user->hostfwd, SLIRP_CFG_HOSTFWD); net_init_slirp_configs(user->guestfwd, 0); - ret = net_slirp_init(vlan, "user", name, user->restrict, vnet, user->host, + ret = net_slirp_init(peer, "user", name, user->restrict, vnet, user->host, user->hostname, user->tftp, user->bootfile, user->dhcpstart, user->dns, user->smb, user->smbserver); diff --git a/net/slirp.h b/net/slirp.h index e2c71ee..5f685c4 100644 --- a/net/slirp.h +++ b/net/slirp.h @@ -32,7 +32,7 @@ #ifdef CONFIG_SLIRP int net_init_slirp(const NetClientOptions *opts, const char *name, - VLANState *vlan); + NetClientState *peer); void net_slirp_hostfwd_add(Monitor *mon, const QDict *qdict); void net_slirp_hostfwd_remove(Monitor *mon, const QDict *qdict); diff --git a/net/socket.c b/net/socket.c index 600c287..c172c24 100644 --- a/net/socket.c +++ b/net/socket.c @@ -34,7 +34,8 @@ #include "qemu_socket.h" typedef struct NetSocketState { - VLANClientState nc; + NetClientState nc; + int listen_fd; int fd; int state; /* 0 = getting length, 1 = getting data */ unsigned int index; @@ -43,15 +44,10 @@ typedef struct NetSocketState { struct sockaddr_in dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */ } NetSocketState; -typedef struct NetSocketListenState { - VLANState *vlan; - char *model; - char *name; - int fd; -} NetSocketListenState; +static void net_socket_accept(void *opaque); /* XXX: we consider we can send the whole packet without blocking */ -static ssize_t net_socket_receive(VLANClientState *nc, const uint8_t *buf, size_t size) +static ssize_t net_socket_receive(NetClientState *nc, const uint8_t *buf, size_t size) { NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc); uint32_t len; @@ -61,7 +57,7 @@ static ssize_t net_socket_receive(VLANClientState *nc, const uint8_t *buf, size_ return send_all(s->fd, buf, size); } -static ssize_t net_socket_receive_dgram(VLANClientState *nc, const uint8_t *buf, size_t size) +static ssize_t net_socket_receive_dgram(NetClientState *nc, const uint8_t *buf, size_t size) { NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc); @@ -86,7 +82,19 @@ static void net_socket_send(void *opaque) /* end of connection */ eoc: qemu_set_fd_handler(s->fd, NULL, NULL, NULL); + if (s->listen_fd != -1) { + qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s); + } closesocket(s->fd); + + s->fd = -1; + s->state = 0; + s->index = 0; + s->packet_len = 0; + s->nc.link_down = true; + memset(s->buf, 0, sizeof(s->buf)); + memset(s->nc.info_str, 0, sizeof(s->nc.info_str)); + return; } buf = buf1; @@ -231,11 +239,19 @@ fail: return -1; } -static void net_socket_cleanup(VLANClientState *nc) +static void net_socket_cleanup(NetClientState *nc) { NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc); - qemu_set_fd_handler(s->fd, NULL, NULL, NULL); - close(s->fd); + if (s->fd != -1) { + qemu_set_fd_handler(s->fd, NULL, NULL, NULL); + close(s->fd); + s->fd = -1; + } + if (s->listen_fd != -1) { + qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL); + closesocket(s->listen_fd); + s->listen_fd = -1; + } } static NetClientInfo net_dgram_socket_info = { @@ -245,7 +261,7 @@ static NetClientInfo net_dgram_socket_info = { .cleanup = net_socket_cleanup, }; -static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, +static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer, const char *model, const char *name, int fd, int is_connected) @@ -253,7 +269,7 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, struct sockaddr_in saddr; int newfd; socklen_t saddr_len; - VLANClientState *nc; + NetClientState *nc; NetSocketState *s; /* fd passed: multicast: "learn" dgram_dst address from bound address and save it @@ -287,7 +303,7 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, } } - nc = qemu_new_net_client(&net_dgram_socket_info, vlan, NULL, model, name); + nc = qemu_new_net_client(&net_dgram_socket_info, peer, model, name); snprintf(nc->info_str, sizeof(nc->info_str), "socket: fd=%d (%s mcast=%s:%d)", @@ -297,11 +313,14 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, s = DO_UPCAST(NetSocketState, nc, nc); s->fd = fd; + s->listen_fd = -1; qemu_set_fd_handler(s->fd, net_socket_send_dgram, NULL, s); /* mcast: save bound address as dst */ - if (is_connected) s->dgram_dst=saddr; + if (is_connected) { + s->dgram_dst = saddr; + } return s; @@ -323,21 +342,22 @@ static NetClientInfo net_socket_info = { .cleanup = net_socket_cleanup, }; -static NetSocketState *net_socket_fd_init_stream(VLANState *vlan, +static NetSocketState *net_socket_fd_init_stream(NetClientState *peer, const char *model, const char *name, int fd, int is_connected) { - VLANClientState *nc; + NetClientState *nc; NetSocketState *s; - nc = qemu_new_net_client(&net_socket_info, vlan, NULL, model, name); + nc = qemu_new_net_client(&net_socket_info, peer, model, name); snprintf(nc->info_str, sizeof(nc->info_str), "socket: fd=%d", fd); s = DO_UPCAST(NetSocketState, nc, nc); s->fd = fd; + s->listen_fd = -1; if (is_connected) { net_socket_connect(s); @@ -347,7 +367,7 @@ static NetSocketState *net_socket_fd_init_stream(VLANState *vlan, return s; } -static NetSocketState *net_socket_fd_init(VLANState *vlan, +static NetSocketState *net_socket_fd_init(NetClientState *peer, const char *model, const char *name, int fd, int is_connected) { @@ -362,60 +382,59 @@ static NetSocketState *net_socket_fd_init(VLANState *vlan, } switch(so_type) { case SOCK_DGRAM: - return net_socket_fd_init_dgram(vlan, model, name, fd, is_connected); + return net_socket_fd_init_dgram(peer, model, name, fd, is_connected); case SOCK_STREAM: - return net_socket_fd_init_stream(vlan, model, name, fd, is_connected); + return net_socket_fd_init_stream(peer, model, name, fd, is_connected); default: /* who knows ... this could be a eg. a pty, do warn and continue as stream */ fprintf(stderr, "qemu: warning: socket type=%d for fd=%d is not SOCK_DGRAM or SOCK_STREAM\n", so_type, fd); - return net_socket_fd_init_stream(vlan, model, name, fd, is_connected); + return net_socket_fd_init_stream(peer, model, name, fd, is_connected); } return NULL; } static void net_socket_accept(void *opaque) { - NetSocketListenState *s = opaque; - NetSocketState *s1; + NetSocketState *s = opaque; struct sockaddr_in saddr; socklen_t len; int fd; for(;;) { len = sizeof(saddr); - fd = qemu_accept(s->fd, (struct sockaddr *)&saddr, &len); + fd = qemu_accept(s->listen_fd, (struct sockaddr *)&saddr, &len); if (fd < 0 && errno != EINTR) { return; } else if (fd >= 0) { + qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL); break; } } - s1 = net_socket_fd_init(s->vlan, s->model, s->name, fd, 1); - if (s1) { - snprintf(s1->nc.info_str, sizeof(s1->nc.info_str), - "socket: connection from %s:%d", - inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); - } + + s->fd = fd; + s->nc.link_down = false; + net_socket_connect(s); + snprintf(s->nc.info_str, sizeof(s->nc.info_str), + "socket: connection from %s:%d", + inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); } -static int net_socket_listen_init(VLANState *vlan, +static int net_socket_listen_init(NetClientState *peer, const char *model, const char *name, const char *host_str) { - NetSocketListenState *s; - int fd, val, ret; + NetClientState *nc; + NetSocketState *s; struct sockaddr_in saddr; + int fd, val, ret; if (parse_host_port(&saddr, host_str) < 0) return -1; - s = g_malloc0(sizeof(NetSocketListenState)); - fd = qemu_socket(PF_INET, SOCK_STREAM, 0); if (fd < 0) { perror("socket"); - g_free(s); return -1; } socket_set_nonblock(fd); @@ -427,26 +446,27 @@ static int net_socket_listen_init(VLANState *vlan, ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)); if (ret < 0) { perror("bind"); - g_free(s); closesocket(fd); return -1; } ret = listen(fd, 0); if (ret < 0) { perror("listen"); - g_free(s); closesocket(fd); return -1; } - s->vlan = vlan; - s->model = g_strdup(model); - s->name = name ? g_strdup(name) : NULL; - s->fd = fd; - qemu_set_fd_handler(fd, net_socket_accept, NULL, s); + + nc = qemu_new_net_client(&net_socket_info, peer, model, name); + s = DO_UPCAST(NetSocketState, nc, nc); + s->fd = -1; + s->listen_fd = fd; + s->nc.link_down = true; + + qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s); return 0; } -static int net_socket_connect_init(VLANState *vlan, +static int net_socket_connect_init(NetClientState *peer, const char *model, const char *name, const char *host_str) @@ -487,7 +507,7 @@ static int net_socket_connect_init(VLANState *vlan, break; } } - s = net_socket_fd_init(vlan, model, name, fd, connected); + s = net_socket_fd_init(peer, model, name, fd, connected); if (!s) return -1; snprintf(s->nc.info_str, sizeof(s->nc.info_str), @@ -496,7 +516,7 @@ static int net_socket_connect_init(VLANState *vlan, return 0; } -static int net_socket_mcast_init(VLANState *vlan, +static int net_socket_mcast_init(NetClientState *peer, const char *model, const char *name, const char *host_str, @@ -522,7 +542,7 @@ static int net_socket_mcast_init(VLANState *vlan, if (fd < 0) return -1; - s = net_socket_fd_init(vlan, model, name, fd, 0); + s = net_socket_fd_init(peer, model, name, fd, 0); if (!s) return -1; @@ -535,7 +555,7 @@ static int net_socket_mcast_init(VLANState *vlan, } -static int net_socket_udp_init(VLANState *vlan, +static int net_socket_udp_init(NetClientState *peer, const char *model, const char *name, const char *rhost, @@ -573,7 +593,7 @@ static int net_socket_udp_init(VLANState *vlan, return -1; } - s = net_socket_fd_init(vlan, model, name, fd, 0); + s = net_socket_fd_init(peer, model, name, fd, 0); if (!s) { return -1; } @@ -587,7 +607,7 @@ static int net_socket_udp_init(VLANState *vlan, } int net_init_socket(const NetClientOptions *opts, const char *name, - VLANState *vlan) + NetClientState *peer) { const NetdevSocketOptions *sock; @@ -610,21 +630,21 @@ int net_init_socket(const NetClientOptions *opts, const char *name, int fd; fd = net_handle_fd_param(cur_mon, sock->fd); - if (fd == -1 || !net_socket_fd_init(vlan, "socket", name, fd, 1)) { + if (fd == -1 || !net_socket_fd_init(peer, "socket", name, fd, 1)) { return -1; } return 0; } if (sock->has_listen) { - if (net_socket_listen_init(vlan, "socket", name, sock->listen) == -1) { + if (net_socket_listen_init(peer, "socket", name, sock->listen) == -1) { return -1; } return 0; } if (sock->has_connect) { - if (net_socket_connect_init(vlan, "socket", name, sock->connect) == + if (net_socket_connect_init(peer, "socket", name, sock->connect) == -1) { return -1; } @@ -634,7 +654,7 @@ int net_init_socket(const NetClientOptions *opts, const char *name, if (sock->has_mcast) { /* if sock->localaddr is missing, it has been initialized to "all bits * zero" */ - if (net_socket_mcast_init(vlan, "socket", name, sock->mcast, + if (net_socket_mcast_init(peer, "socket", name, sock->mcast, sock->localaddr) == -1) { return -1; } @@ -646,7 +666,7 @@ int net_init_socket(const NetClientOptions *opts, const char *name, error_report("localaddr= is mandatory with udp="); return -1; } - if (net_socket_udp_init(vlan, "udp", name, sock->udp, sock->localaddr) == + if (net_socket_udp_init(peer, "udp", name, sock->udp, sock->localaddr) == -1) { return -1; } diff --git a/net/socket.h b/net/socket.h index c4809ad..3f8a092 100644 --- a/net/socket.h +++ b/net/socket.h @@ -28,6 +28,6 @@ #include "qapi-types.h" int net_init_socket(const NetClientOptions *opts, const char *name, - VLANState *vlan); + NetClientState *peer); #endif /* QEMU_NET_SOCKET_H */ diff --git a/net/tap-win32.c b/net/tap-win32.c index 2328072..c0ea954 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -630,11 +630,11 @@ static int tap_win32_open(tap_win32_overlapped_t **phandle, /********************************************/ typedef struct TAPState { - VLANClientState nc; + NetClientState nc; tap_win32_overlapped_t *handle; } TAPState; -static void tap_cleanup(VLANClientState *nc) +static void tap_cleanup(NetClientState *nc) { TAPState *s = DO_UPCAST(TAPState, nc, nc); @@ -645,7 +645,7 @@ static void tap_cleanup(VLANClientState *nc) */ } -static ssize_t tap_receive(VLANClientState *nc, const uint8_t *buf, size_t size) +static ssize_t tap_receive(NetClientState *nc, const uint8_t *buf, size_t size) { TAPState *s = DO_UPCAST(TAPState, nc, nc); @@ -673,10 +673,10 @@ static NetClientInfo net_tap_win32_info = { .cleanup = tap_cleanup, }; -static int tap_win32_init(VLANState *vlan, const char *model, +static int tap_win32_init(NetClientState *peer, const char *model, const char *name, const char *ifname) { - VLANClientState *nc; + NetClientState *nc; TAPState *s; tap_win32_overlapped_t *handle; @@ -685,7 +685,7 @@ static int tap_win32_init(VLANState *vlan, const char *model, return -1; } - nc = qemu_new_net_client(&net_tap_win32_info, vlan, NULL, model, name); + nc = qemu_new_net_client(&net_tap_win32_info, peer, model, name); s = DO_UPCAST(TAPState, nc, nc); @@ -700,7 +700,7 @@ static int tap_win32_init(VLANState *vlan, const char *model, } int net_init_tap(const NetClientOptions *opts, const char *name, - VLANState *vlan) + NetClientState *peer) { const NetdevTapOptions *tap; @@ -712,19 +712,19 @@ int net_init_tap(const NetClientOptions *opts, const char *name, return -1; } - if (tap_win32_init(vlan, "tap", name, tap->ifname) == -1) { + if (tap_win32_init(peer, "tap", name, tap->ifname) == -1) { return -1; } return 0; } -int tap_has_ufo(VLANClientState *vc) +int tap_has_ufo(NetClientState *nc) { return 0; } -int tap_has_vnet_hdr(VLANClientState *vc) +int tap_has_vnet_hdr(NetClientState *nc) { return 0; } @@ -738,16 +738,16 @@ void tap_fd_set_vnet_hdr_len(int fd, int len) { } -void tap_using_vnet_hdr(VLANClientState *vc, int using_vnet_hdr) +void tap_using_vnet_hdr(NetClientState *nc, int using_vnet_hdr) { } -void tap_set_offload(VLANClientState *vc, int csum, int tso4, +void tap_set_offload(NetClientState *nc, int csum, int tso4, int tso6, int ecn, int ufo) { } -struct vhost_net *tap_get_vhost_net(VLANClientState *nc) +struct vhost_net *tap_get_vhost_net(NetClientState *nc) { return NULL; } @@ -50,7 +50,7 @@ #define TAP_BUFSIZE (4096 + 65536) typedef struct TAPState { - VLANClientState nc; + NetClientState nc; int fd; char down_script[1024]; char down_script_arg[128]; @@ -115,7 +115,7 @@ static ssize_t tap_write_packet(TAPState *s, const struct iovec *iov, int iovcnt return len; } -static ssize_t tap_receive_iov(VLANClientState *nc, const struct iovec *iov, +static ssize_t tap_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt) { TAPState *s = DO_UPCAST(TAPState, nc, nc); @@ -134,7 +134,7 @@ static ssize_t tap_receive_iov(VLANClientState *nc, const struct iovec *iov, return tap_write_packet(s, iovp, iovcnt); } -static ssize_t tap_receive_raw(VLANClientState *nc, const uint8_t *buf, size_t size) +static ssize_t tap_receive_raw(NetClientState *nc, const uint8_t *buf, size_t size) { TAPState *s = DO_UPCAST(TAPState, nc, nc); struct iovec iov[2]; @@ -154,7 +154,7 @@ static ssize_t tap_receive_raw(VLANClientState *nc, const uint8_t *buf, size_t s return tap_write_packet(s, iov, iovcnt); } -static ssize_t tap_receive(VLANClientState *nc, const uint8_t *buf, size_t size) +static ssize_t tap_receive(NetClientState *nc, const uint8_t *buf, size_t size) { TAPState *s = DO_UPCAST(TAPState, nc, nc); struct iovec iov[1]; @@ -183,7 +183,7 @@ ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen) } #endif -static void tap_send_completed(VLANClientState *nc, ssize_t len) +static void tap_send_completed(NetClientState *nc, ssize_t len) { TAPState *s = DO_UPCAST(TAPState, nc, nc); tap_read_poll(s, 1); @@ -214,7 +214,7 @@ static void tap_send(void *opaque) } while (size > 0 && qemu_can_send_packet(&s->nc)); } -int tap_has_ufo(VLANClientState *nc) +int tap_has_ufo(NetClientState *nc) { TAPState *s = DO_UPCAST(TAPState, nc, nc); @@ -223,7 +223,7 @@ int tap_has_ufo(VLANClientState *nc) return s->has_ufo; } -int tap_has_vnet_hdr(VLANClientState *nc) +int tap_has_vnet_hdr(NetClientState *nc) { TAPState *s = DO_UPCAST(TAPState, nc, nc); @@ -232,7 +232,7 @@ int tap_has_vnet_hdr(VLANClientState *nc) return !!s->host_vnet_hdr_len; } -int tap_has_vnet_hdr_len(VLANClientState *nc, int len) +int tap_has_vnet_hdr_len(NetClientState *nc, int len) { TAPState *s = DO_UPCAST(TAPState, nc, nc); @@ -241,7 +241,7 @@ int tap_has_vnet_hdr_len(VLANClientState *nc, int len) return tap_probe_vnet_hdr_len(s->fd, len); } -void tap_set_vnet_hdr_len(VLANClientState *nc, int len) +void tap_set_vnet_hdr_len(NetClientState *nc, int len) { TAPState *s = DO_UPCAST(TAPState, nc, nc); @@ -253,7 +253,7 @@ void tap_set_vnet_hdr_len(VLANClientState *nc, int len) s->host_vnet_hdr_len = len; } -void tap_using_vnet_hdr(VLANClientState *nc, int using_vnet_hdr) +void tap_using_vnet_hdr(NetClientState *nc, int using_vnet_hdr) { TAPState *s = DO_UPCAST(TAPState, nc, nc); @@ -265,7 +265,7 @@ void tap_using_vnet_hdr(VLANClientState *nc, int using_vnet_hdr) s->using_vnet_hdr = using_vnet_hdr; } -void tap_set_offload(VLANClientState *nc, int csum, int tso4, +void tap_set_offload(NetClientState *nc, int csum, int tso4, int tso6, int ecn, int ufo) { TAPState *s = DO_UPCAST(TAPState, nc, nc); @@ -276,7 +276,7 @@ void tap_set_offload(VLANClientState *nc, int csum, int tso4, tap_fd_set_offload(s->fd, csum, tso4, tso6, ecn, ufo); } -static void tap_cleanup(VLANClientState *nc) +static void tap_cleanup(NetClientState *nc) { TAPState *s = DO_UPCAST(TAPState, nc, nc); @@ -296,14 +296,14 @@ static void tap_cleanup(VLANClientState *nc) s->fd = -1; } -static void tap_poll(VLANClientState *nc, bool enable) +static void tap_poll(NetClientState *nc, bool enable) { TAPState *s = DO_UPCAST(TAPState, nc, nc); tap_read_poll(s, enable); tap_write_poll(s, enable); } -int tap_get_fd(VLANClientState *nc) +int tap_get_fd(NetClientState *nc) { TAPState *s = DO_UPCAST(TAPState, nc, nc); assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP); @@ -322,16 +322,16 @@ static NetClientInfo net_tap_info = { .cleanup = tap_cleanup, }; -static TAPState *net_tap_fd_init(VLANState *vlan, +static TAPState *net_tap_fd_init(NetClientState *peer, const char *model, const char *name, int fd, int vnet_hdr) { - VLANClientState *nc; + NetClientState *nc; TAPState *s; - nc = qemu_new_net_client(&net_tap_info, vlan, NULL, model, name); + nc = qemu_new_net_client(&net_tap_info, peer, model, name); s = DO_UPCAST(TAPState, nc, nc); @@ -514,7 +514,7 @@ static int net_bridge_run_helper(const char *helper, const char *bridge) } int net_init_bridge(const NetClientOptions *opts, const char *name, - VLANState *vlan) + NetClientState *peer) { const NetdevBridgeOptions *bridge; const char *helper, *br; @@ -537,7 +537,7 @@ int net_init_bridge(const NetClientOptions *opts, const char *name, vnet_hdr = tap_probe_vnet_hdr(fd); - s = net_tap_fd_init(vlan, "bridge", name, fd, vnet_hdr); + s = net_tap_fd_init(peer, "bridge", name, fd, vnet_hdr); if (!s) { close(fd); return -1; @@ -587,7 +587,7 @@ static int net_tap_init(const NetdevTapOptions *tap, int *vnet_hdr, } int net_init_tap(const NetClientOptions *opts, const char *name, - VLANState *vlan) + NetClientState *peer) { const NetdevTapOptions *tap; @@ -650,7 +650,7 @@ int net_init_tap(const NetClientOptions *opts, const char *name, model = "tap"; } - s = net_tap_fd_init(vlan, model, name, fd, vnet_hdr); + s = net_tap_fd_init(peer, model, name, fd, vnet_hdr); if (!s) { close(fd); return -1; @@ -708,7 +708,7 @@ int net_init_tap(const NetClientOptions *opts, const char *name, return 0; } -VHostNetState *tap_get_vhost_net(VLANClientState *nc) +VHostNetState *tap_get_vhost_net(NetClientState *nc) { TAPState *s = DO_UPCAST(TAPState, nc, nc); assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP); @@ -33,18 +33,18 @@ #define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown" int net_init_tap(const NetClientOptions *opts, const char *name, - VLANState *vlan); + NetClientState *peer); int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required); ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen); -int tap_has_ufo(VLANClientState *vc); -int tap_has_vnet_hdr(VLANClientState *vc); -int tap_has_vnet_hdr_len(VLANClientState *vc, int len); -void tap_using_vnet_hdr(VLANClientState *vc, int using_vnet_hdr); -void tap_set_offload(VLANClientState *vc, int csum, int tso4, int tso6, int ecn, int ufo); -void tap_set_vnet_hdr_len(VLANClientState *vc, int len); +int tap_has_ufo(NetClientState *nc); +int tap_has_vnet_hdr(NetClientState *nc); +int tap_has_vnet_hdr_len(NetClientState *nc, int len); +void tap_using_vnet_hdr(NetClientState *nc, int using_vnet_hdr); +void tap_set_offload(NetClientState *nc, int csum, int tso4, int tso6, int ecn, int ufo); +void tap_set_vnet_hdr_len(NetClientState *nc, int len); int tap_set_sndbuf(int fd, const NetdevTapOptions *tap); int tap_probe_vnet_hdr(int fd); @@ -53,12 +53,12 @@ int tap_probe_has_ufo(int fd); void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo); void tap_fd_set_vnet_hdr_len(int fd, int len); -int tap_get_fd(VLANClientState *vc); +int tap_get_fd(NetClientState *nc); struct vhost_net; -struct vhost_net *tap_get_vhost_net(VLANClientState *vc); +struct vhost_net *tap_get_vhost_net(NetClientState *nc); int net_init_bridge(const NetClientOptions *opts, const char *name, - VLANState *vlan); + NetClientState *peer); #endif /* QEMU_NET_TAP_H */ @@ -33,7 +33,7 @@ #include "qemu-option.h" typedef struct VDEState { - VLANClientState nc; + NetClientState nc; VDECONN *vde; } VDEState; @@ -49,7 +49,7 @@ static void vde_to_qemu(void *opaque) } } -static ssize_t vde_receive(VLANClientState *nc, const uint8_t *buf, size_t size) +static ssize_t vde_receive(NetClientState *nc, const uint8_t *buf, size_t size) { VDEState *s = DO_UPCAST(VDEState, nc, nc); ssize_t ret; @@ -61,7 +61,7 @@ static ssize_t vde_receive(VLANClientState *nc, const uint8_t *buf, size_t size) return ret; } -static void vde_cleanup(VLANClientState *nc) +static void vde_cleanup(NetClientState *nc) { VDEState *s = DO_UPCAST(VDEState, nc, nc); qemu_set_fd_handler(vde_datafd(s->vde), NULL, NULL, NULL); @@ -75,11 +75,11 @@ static NetClientInfo net_vde_info = { .cleanup = vde_cleanup, }; -static int net_vde_init(VLANState *vlan, const char *model, +static int net_vde_init(NetClientState *peer, const char *model, const char *name, const char *sock, int port, const char *group, int mode) { - VLANClientState *nc; + NetClientState *nc; VDEState *s; VDECONN *vde; char *init_group = (char *)group; @@ -96,7 +96,7 @@ static int net_vde_init(VLANState *vlan, const char *model, return -1; } - nc = qemu_new_net_client(&net_vde_info, vlan, NULL, model, name); + nc = qemu_new_net_client(&net_vde_info, peer, model, name); snprintf(nc->info_str, sizeof(nc->info_str), "sock=%s,fd=%d", sock, vde_datafd(vde)); @@ -111,7 +111,7 @@ static int net_vde_init(VLANState *vlan, const char *model, } int net_init_vde(const NetClientOptions *opts, const char *name, - VLANState *vlan) + NetClientState *peer) { const NetdevVdeOptions *vde; @@ -119,7 +119,7 @@ int net_init_vde(const NetClientOptions *opts, const char *name, vde = opts->vde; /* missing optional values have been initialized to "all bits zero" */ - if (net_vde_init(vlan, "vde", name, vde->sock, vde->port, vde->group, + if (net_vde_init(peer, "vde", name, vde->sock, vde->port, vde->group, vde->has_mode ? vde->mode : 0700) == -1) { return -1; } @@ -30,7 +30,7 @@ #ifdef CONFIG_VDE int net_init_vde(const NetClientOptions *opts, const char *name, - VLANState *vlan); + NetClientState *peer); #endif /* CONFIG_VDE */ diff --git a/qapi-schema.json b/qapi-schema.json index bc55ed2..e4a19cf 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -2094,6 +2094,19 @@ '*helper': 'str' } } ## +# @NetdevHubPortOptions +# +# Connect two or more net clients through a software hub. +# +# @hubid: hub identifier number +# +# Since 1.2 +## +{ 'type': 'NetdevHubPortOptions', + 'data': { + 'hubid': 'int32' } } + +## # @NetClientOptions # # A discriminated record of network device traits. @@ -2102,14 +2115,15 @@ ## { 'union': 'NetClientOptions', 'data': { - 'none': 'NetdevNoneOptions', - 'nic': 'NetLegacyNicOptions', - 'user': 'NetdevUserOptions', - 'tap': 'NetdevTapOptions', - 'socket': 'NetdevSocketOptions', - 'vde': 'NetdevVdeOptions', - 'dump': 'NetdevDumpOptions', - 'bridge': 'NetdevBridgeOptions' } } + 'none': 'NetdevNoneOptions', + 'nic': 'NetLegacyNicOptions', + 'user': 'NetdevUserOptions', + 'tap': 'NetdevTapOptions', + 'socket': 'NetdevSocketOptions', + 'vde': 'NetdevVdeOptions', + 'dump': 'NetdevDumpOptions', + 'bridge': 'NetdevBridgeOptions', + 'hubport': 'NetdevHubPortOptions' } } ## # @NetLegacy diff --git a/qemu-bridge-helper.c b/qemu-bridge-helper.c index aec5008..652eec9 100644 --- a/qemu-bridge-helper.c +++ b/qemu-bridge-helper.c @@ -35,6 +35,10 @@ #include <linux/sockios.h> +#ifndef SIOCBRADDIF +#include <linux/if_bridge.h> +#endif + #include "qemu-queue.h" #include "net/tap-linux.h" @@ -221,6 +225,10 @@ static int drop_privileges(void) int main(int argc, char **argv) { struct ifreq ifr; +#ifndef SIOCBRADDIF + unsigned long ifargs[4]; +#endif + int ifindex; int fd, ctlfd, unixfd = -1; int use_vnet = 0; int mtu; @@ -361,9 +369,19 @@ int main(int argc, char **argv) /* add the interface to the bridge */ prep_ifreq(&ifr, bridge); - ifr.ifr_ifindex = if_nametoindex(iface); - - if (ioctl(ctlfd, SIOCBRADDIF, &ifr) == -1) { + ifindex = if_nametoindex(iface); +#ifndef SIOCBRADDIF + ifargs[0] = BRCTL_ADD_IF; + ifargs[1] = ifindex; + ifargs[2] = 0; + ifargs[3] = 0; + ifr.ifr_data = (void *)ifargs; + ret = ioctl(ctlfd, SIOCDEVPRIVATE, &ifr); +#else + ifr.ifr_ifindex = ifindex; + ret = ioctl(ctlfd, SIOCBRADDIF, &ifr); +#endif + if (ret == -1) { fprintf(stderr, "failed to add interface `%s' to bridge `%s': %s\n", iface, bridge, strerror(errno)); ret = EXIT_FAILURE; diff --git a/qemu-common.h b/qemu-common.h index dd91912..f16079f 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -252,8 +252,7 @@ typedef struct TextConsole TextConsole; typedef TextConsole QEMUConsole; typedef struct CharDriverState CharDriverState; typedef struct MACAddr MACAddr; -typedef struct VLANState VLANState; -typedef struct VLANClientState VLANClientState; +typedef struct NetClientState NetClientState; typedef struct i2c_bus i2c_bus; typedef struct ISABus ISABus; typedef struct ISADevice ISADevice; @@ -177,11 +177,6 @@ void if_start(Slirp *slirp) } while (ifm_next) { - /* check if we can really output */ - if (!slirp_can_output(slirp->opaque)) { - break; - } - ifm = ifm_next; from_batchq = next_from_batchq; diff --git a/slirp/libslirp.h b/slirp/libslirp.h index 77527ad..9b471b5 100644 --- a/slirp/libslirp.h +++ b/slirp/libslirp.h @@ -25,7 +25,6 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len); /* you must provide the following functions: */ -int slirp_can_output(void *opaque); void slirp_output(void *opaque, const uint8_t *pkt, int pkt_len); int slirp_add_hostfwd(Slirp *slirp, int is_udp, |