diff options
-rw-r--r-- | MAINTAINERS | 2 | ||||
-rw-r--r-- | docs/colo-proxy.txt | 3 | ||||
-rw-r--r-- | hw/net/e1000.c | 4 | ||||
-rw-r--r-- | hw/net/e1000_regs.h | 2 | ||||
-rw-r--r-- | hw/net/e1000e_core.c | 2 | ||||
-rw-r--r-- | hw/net/e1000x_common.h | 2 | ||||
-rw-r--r-- | hw/net/rocker/rocker.c | 94 | ||||
-rw-r--r-- | hw/net/rocker/rocker_desc.c | 10 | ||||
-rw-r--r-- | hw/net/rocker/rocker_fp.c | 4 | ||||
-rw-r--r-- | hw/net/rocker/rocker_of_dpa.c | 20 | ||||
-rw-r--r-- | hw/net/rocker/rocker_world.c | 12 | ||||
-rw-r--r-- | hw/net/rtl8139.c | 53 | ||||
-rw-r--r-- | include/qemu/sockets.h | 3 | ||||
-rw-r--r-- | include/sysemu/iothread.h | 4 | ||||
-rw-r--r-- | iothread.c | 45 | ||||
-rw-r--r-- | net/colo-compare.c | 183 | ||||
-rw-r--r-- | net/filter-rewriter.c | 6 | ||||
-rw-r--r-- | net/net.c | 22 | ||||
-rw-r--r-- | net/socket.c | 156 |
19 files changed, 304 insertions, 323 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index caf7e8a..36eeb42 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1577,7 +1577,7 @@ F: include/migration/failover.h F: docs/COLO-FT.txt COLO Proxy -M: Zhang Chen <zhangchen.fnst@cn.fujitsu.com> +M: Zhang Chen <zhangckid@gmail.com> M: Li Zhijian <lizhijian@cn.fujitsu.com> S: Supported F: docs/colo-proxy.txt diff --git a/docs/colo-proxy.txt b/docs/colo-proxy.txt index f6a624f..8b726ea 100644 --- a/docs/colo-proxy.txt +++ b/docs/colo-proxy.txt @@ -170,10 +170,11 @@ Primary(ip:3.3.3.3): -chardev socket,id=compare0-0,host=3.3.3.3,port=9001 -chardev socket,id=compare_out,host=3.3.3.3,port=9005,server,nowait -chardev socket,id=compare_out0,host=3.3.3.3,port=9005 +-object iothread,id=iothread1 -object filter-mirror,id=m0,netdev=hn0,queue=tx,outdev=mirror0 -object filter-redirector,netdev=hn0,id=redire0,queue=rx,indev=compare_out -object filter-redirector,netdev=hn0,id=redire1,queue=rx,outdev=compare0 --object colo-compare,id=comp0,primary_in=compare0-0,secondary_in=compare1,outdev=compare_out0 +-object colo-compare,id=comp0,primary_in=compare0-0,secondary_in=compare1,outdev=compare_out0,iothread=iothread1 Secondary(ip:3.3.3.8): -netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,down script=/etc/qemu-ifdown diff --git a/hw/net/e1000.c b/hw/net/e1000.c index f2e5072..eebe3a9 100644 --- a/hw/net/e1000.c +++ b/hw/net/e1000.c @@ -1127,7 +1127,7 @@ static uint32_t (*macreg_readops[])(E1000State *, int) = { getreg(TADV), getreg(ITR), getreg(FCRUC), getreg(IPAV), getreg(WUC), getreg(WUS), getreg(SCC), getreg(ECOL), getreg(MCC), getreg(LATECOL), getreg(COLC), getreg(DC), - getreg(TNCRS), getreg(SEC), getreg(CEXTERR), getreg(RLEC), + getreg(TNCRS), getreg(SEQEC), getreg(CEXTERR), getreg(RLEC), getreg(XONRXC), getreg(XONTXC), getreg(XOFFRXC), getreg(XOFFTXC), getreg(RFC), getreg(RJC), getreg(RNBC), getreg(TSCTFC), getreg(MGTPRC), getreg(MGTPDC), getreg(MGTPTC), getreg(GORCL), @@ -1223,7 +1223,7 @@ static const uint8_t mac_reg_access[0x8000] = { [FFLT] = markflag(MAC), [FFMT] = markflag(MAC), [SCC] = markflag(MAC), [FCRUC] = markflag(MAC), [LATECOL] = markflag(MAC), [COLC] = markflag(MAC), - [SEC] = markflag(MAC), [CEXTERR] = markflag(MAC), + [SEQEC] = markflag(MAC), [CEXTERR] = markflag(MAC), [XONTXC] = markflag(MAC), [XOFFRXC] = markflag(MAC), [RJC] = markflag(MAC), [RNBC] = markflag(MAC), [MGTPDC] = markflag(MAC), [MGTPTC] = markflag(MAC), diff --git a/hw/net/e1000_regs.h b/hw/net/e1000_regs.h index 23eed50..ae99f58 100644 --- a/hw/net/e1000_regs.h +++ b/hw/net/e1000_regs.h @@ -260,7 +260,7 @@ #define E1000_COLC 0x04028 /* Collision Count - R/clr */ #define E1000_DC 0x04030 /* Defer Count - R/clr */ #define E1000_TNCRS 0x04034 /* TX-No CRS - R/clr */ -#define E1000_SEC 0x04038 /* Sequence Error Count - R/clr */ +#define E1000_SEQEC 0x04038 /* Sequence Error Count - R/clr */ #define E1000_CEXTERR 0x0403C /* Carrier Extension Error Count - R/clr */ #define E1000_RLEC 0x04040 /* Receive Length Error Count - R/clr */ #define E1000_XONRXC 0x04048 /* XON RX Count - R/clr */ diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c index 8140564..43a8d89 100644 --- a/hw/net/e1000e_core.c +++ b/hw/net/e1000e_core.c @@ -2855,7 +2855,7 @@ static uint32_t (*e1000e_macreg_readops[])(E1000ECore *, int) = { e1000e_getreg(RDLEN0), e1000e_getreg(RDH1), e1000e_getreg(LATECOL), - e1000e_getreg(SEC), + e1000e_getreg(SEQEC), e1000e_getreg(XONTXC), e1000e_getreg(WUS), e1000e_getreg(GORCL), diff --git a/hw/net/e1000x_common.h b/hw/net/e1000x_common.h index 21bf28e..3072ce9 100644 --- a/hw/net/e1000x_common.h +++ b/hw/net/e1000x_common.h @@ -40,7 +40,7 @@ enum { defreg(VFTA), defreg(VET), defreg(RDTR), defreg(RADV), defreg(TADV), defreg(ITR), defreg(SCC), defreg(ECOL), defreg(MCC), defreg(LATECOL), defreg(COLC), defreg(DC), - defreg(TNCRS), defreg(SEC), defreg(CEXTERR), defreg(RLEC), + defreg(TNCRS), defreg(SEQEC), defreg(CEXTERR), defreg(RLEC), defreg(XONRXC), defreg(XONTXC), defreg(XOFFRXC), defreg(XOFFTXC), defreg(FCRUC), defreg(AIT), defreg(TDFH), defreg(TDFT), defreg(TDFHS), defreg(TDFTS), defreg(TDFPC), defreg(WUC), diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c index 4f0f6d7..9273473 100644 --- a/hw/net/rocker/rocker.c +++ b/hw/net/rocker/rocker.c @@ -69,10 +69,10 @@ struct rocker { QLIST_ENTRY(rocker) next; }; -#define ROCKER "rocker" +#define TYPE_ROCKER "rocker" -#define to_rocker(obj) \ - OBJECT_CHECK(Rocker, (obj), ROCKER) +#define ROCKER(obj) \ + OBJECT_CHECK(Rocker, (obj), TYPE_ROCKER) static QLIST_HEAD(, rocker) rockers; @@ -239,10 +239,6 @@ static int tx_consume(Rocker *r, DescInfo *info) } iov[iovcnt].iov_len = frag_len; iov[iovcnt].iov_base = g_malloc(frag_len); - if (!iov[iovcnt].iov_base) { - err = -ROCKER_ENOMEM; - goto err_no_mem; - } pci_dma_read(dev, frag_addr, iov[iovcnt].iov_base, iov[iovcnt].iov_len); @@ -259,7 +255,6 @@ static int tx_consume(Rocker *r, DescInfo *info) err = fp_port_eg(r->fp_port[port], iov, iovcnt); err_too_many_frags: -err_no_mem: err_bad_attr: for (i = 0; i < ROCKER_TX_FRAGS_MAX; i++) { g_free(iov[i].iov_base); @@ -671,10 +666,7 @@ int rx_produce(World *world, uint32_t pport, */ data = g_malloc(data_size); - if (!data) { - err = -ROCKER_ENOMEM; - goto out; - } + iov_to_buf(iov, iovcnt, 0, data, data_size); pci_dma_write(dev, frag_addr, data, data_size); g_free(data); @@ -719,11 +711,6 @@ static void rocker_test_dma_ctrl(Rocker *r, uint32_t val) buf = g_malloc(r->test_dma_size); - if (!buf) { - DPRINTF("test dma buffer alloc failed"); - return; - } - switch (val) { case ROCKER_TEST_DMA_CTRL_CLEAR: memset(buf, 0, r->test_dma_size); @@ -1249,20 +1236,18 @@ rollback: return err; } -static int rocker_msix_init(Rocker *r) +static int rocker_msix_init(Rocker *r, Error **errp) { PCIDevice *dev = PCI_DEVICE(r); int err; - Error *local_err = NULL; err = msix_init(dev, ROCKER_MSIX_VEC_COUNT(r->fp_ports), &r->msix_bar, ROCKER_PCI_MSIX_BAR_IDX, ROCKER_PCI_MSIX_TABLE_OFFSET, &r->msix_bar, ROCKER_PCI_MSIX_BAR_IDX, ROCKER_PCI_MSIX_PBA_OFFSET, - 0, &local_err); + 0, errp); if (err) { - error_report_err(local_err); return err; } @@ -1298,9 +1283,9 @@ static World *rocker_world_type_by_name(Rocker *r, const char *name) return NULL; } -static int pci_rocker_init(PCIDevice *dev) +static void pci_rocker_realize(PCIDevice *dev, Error **errp) { - Rocker *r = to_rocker(dev); + Rocker *r = ROCKER(dev); const MACAddr zero = { .a = { 0, 0, 0, 0, 0, 0 } }; const MACAddr dflt = { .a = { 0x52, 0x54, 0x00, 0x12, 0x35, 0x01 } }; static int sw_index; @@ -1310,23 +1295,15 @@ static int pci_rocker_init(PCIDevice *dev) r->worlds[ROCKER_WORLD_TYPE_OF_DPA] = of_dpa_world_alloc(r); - for (i = 0; i < ROCKER_WORLD_TYPE_MAX; i++) { - if (!r->worlds[i]) { - err = -ENOMEM; - goto err_world_alloc; - } - } - if (!r->world_name) { r->world_name = g_strdup(world_name(r->worlds[ROCKER_WORLD_TYPE_OF_DPA])); } r->world_dflt = rocker_world_type_by_name(r, r->world_name); if (!r->world_dflt) { - fprintf(stderr, - "rocker: requested world \"%s\" does not exist\n", + error_setg(errp, + "invalid argument requested world %s does not exist", r->world_name); - err = -EINVAL; goto err_world_type_by_name; } @@ -1346,7 +1323,7 @@ static int pci_rocker_init(PCIDevice *dev) /* MSI-X init */ - err = rocker_msix_init(r); + err = rocker_msix_init(r, errp); if (err) { goto err_msix_init; } @@ -1354,11 +1331,11 @@ static int pci_rocker_init(PCIDevice *dev) /* validate switch properties */ if (!r->name) { - r->name = g_strdup(ROCKER); + r->name = g_strdup(TYPE_ROCKER); } if (rocker_find(r->name)) { - err = -EEXIST; + error_setg(errp, "%s already exists", r->name); goto err_duplicate; } @@ -1372,10 +1349,10 @@ static int pci_rocker_init(PCIDevice *dev) #define ROCKER_IFNAMSIZ 16 #define MAX_ROCKER_NAME_LEN (ROCKER_IFNAMSIZ - 1 - 3 - 3) if (strlen(r->name) > MAX_ROCKER_NAME_LEN) { - fprintf(stderr, - "rocker: name too long; please shorten to at most %d chars\n", + error_setg(errp, + "name too long; please shorten to at most %d chars", MAX_ROCKER_NAME_LEN); - return -EINVAL; + goto err_name_too_long; } if (memcmp(&r->fp_start_macaddr, &zero, sizeof(zero)) == 0) { @@ -1393,9 +1370,6 @@ static int pci_rocker_init(PCIDevice *dev) } r->rings = g_new(DescRing *, rocker_pci_ring_count(r)); - if (!r->rings) { - goto err_rings_alloc; - } /* Rings are ordered like this: * - command ring @@ -1407,14 +1381,9 @@ static int pci_rocker_init(PCIDevice *dev) * ..... */ - err = -ENOMEM; for (i = 0; i < rocker_pci_ring_count(r); i++) { DescRing *ring = desc_ring_alloc(r, i); - if (!ring) { - goto err_ring_alloc; - } - if (i == ROCKER_RING_CMD) { desc_ring_set_consume(ring, cmd_consume, ROCKER_MSIX_VEC_CMD); } else if (i == ROCKER_RING_EVENT) { @@ -1434,48 +1403,31 @@ static int pci_rocker_init(PCIDevice *dev) fp_port_alloc(r, r->name, &r->fp_start_macaddr, i, &r->fp_ports_peers[i]); - if (!port) { - goto err_port_alloc; - } - r->fp_port[i] = port; fp_port_set_world(port, r->world_dflt); } QLIST_INSERT_HEAD(&rockers, r, next); - return 0; + return; -err_port_alloc: - for (--i; i >= 0; i--) { - FpPort *port = r->fp_port[i]; - fp_port_free(port); - } - i = rocker_pci_ring_count(r); -err_ring_alloc: - for (--i; i >= 0; i--) { - desc_ring_free(r->rings[i]); - } - g_free(r->rings); -err_rings_alloc: +err_name_too_long: err_duplicate: rocker_msix_uninit(r); err_msix_init: object_unparent(OBJECT(&r->msix_bar)); object_unparent(OBJECT(&r->mmio)); err_world_type_by_name: -err_world_alloc: for (i = 0; i < ROCKER_WORLD_TYPE_MAX; i++) { if (r->worlds[i]) { world_free(r->worlds[i]); } } - return err; } static void pci_rocker_uninit(PCIDevice *dev) { - Rocker *r = to_rocker(dev); + Rocker *r = ROCKER(dev); int i; QLIST_REMOVE(r, next); @@ -1508,7 +1460,7 @@ static void pci_rocker_uninit(PCIDevice *dev) static void rocker_reset(DeviceState *dev) { - Rocker *r = to_rocker(dev); + Rocker *r = ROCKER(dev); int i; for (i = 0; i < ROCKER_WORLD_TYPE_MAX; i++) { @@ -1546,7 +1498,7 @@ static Property rocker_properties[] = { }; static const VMStateDescription rocker_vmsd = { - .name = ROCKER, + .name = TYPE_ROCKER, .unmigratable = 1, }; @@ -1555,7 +1507,7 @@ static void rocker_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = pci_rocker_init; + k->realize = pci_rocker_realize; k->exit = pci_rocker_uninit; k->vendor_id = PCI_VENDOR_ID_REDHAT; k->device_id = PCI_DEVICE_ID_REDHAT_ROCKER; @@ -1569,7 +1521,7 @@ static void rocker_class_init(ObjectClass *klass, void *data) } static const TypeInfo rocker_info = { - .name = ROCKER, + .name = TYPE_ROCKER, .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(Rocker), .class_init = rocker_class_init, diff --git a/hw/net/rocker/rocker_desc.c b/hw/net/rocker/rocker_desc.c index 6184c40..b009da4 100644 --- a/hw/net/rocker/rocker_desc.c +++ b/hw/net/rocker/rocker_desc.c @@ -65,10 +65,6 @@ char *desc_get_buf(DescInfo *info, bool read_only) info->buf_size = size; } - if (!info->buf) { - return NULL; - } - pci_dma_read(dev, le64_to_cpu(info->desc.buf_addr), info->buf, size); return info->buf; @@ -142,9 +138,6 @@ bool desc_ring_set_size(DescRing *ring, uint32_t size) ring->head = ring->tail = 0; ring->info = g_renew(DescInfo, ring->info, size); - if (!ring->info) { - return false; - } memset(ring->info, 0, size * sizeof(DescInfo)); @@ -345,9 +338,6 @@ DescRing *desc_ring_alloc(Rocker *r, int index) DescRing *ring; ring = g_new0(DescRing, 1); - if (!ring) { - return NULL; - } ring->r = r; ring->index = index; diff --git a/hw/net/rocker/rocker_fp.c b/hw/net/rocker/rocker_fp.c index 1305ac3..4b3c984 100644 --- a/hw/net/rocker/rocker_fp.c +++ b/hw/net/rocker/rocker_fp.c @@ -226,10 +226,6 @@ FpPort *fp_port_alloc(Rocker *r, char *sw_name, { FpPort *port = g_new0(FpPort, 1); - if (!port) { - return NULL; - } - port->r = r; port->index = index; port->pport = index + 1; diff --git a/hw/net/rocker/rocker_of_dpa.c b/hw/net/rocker/rocker_of_dpa.c index 9b1e0d2..191a58e 100644 --- a/hw/net/rocker/rocker_of_dpa.c +++ b/hw/net/rocker/rocker_of_dpa.c @@ -368,9 +368,6 @@ static OfDpaFlow *of_dpa_flow_alloc(uint64_t cookie) int64_t now = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) / 1000; flow = g_new0(OfDpaFlow, 1); - if (!flow) { - return NULL; - } flow->cookie = cookie; flow->mask.tbl_id = 0xffffffff; @@ -813,10 +810,6 @@ static OfDpaGroup *of_dpa_group_alloc(uint32_t id) { OfDpaGroup *group = g_new0(OfDpaGroup, 1); - if (!group) { - return NULL; - } - group->id = id; return group; @@ -1867,9 +1860,6 @@ static int of_dpa_cmd_flow_add(OfDpa *of_dpa, uint64_t cookie, } flow = of_dpa_flow_alloc(cookie); - if (!flow) { - return -ROCKER_ENOMEM; - } err = of_dpa_cmd_flow_add_mod(of_dpa, flow, flow_tlvs); if (err) { @@ -2040,17 +2030,10 @@ static int of_dpa_cmd_add_l2_flood(OfDpa *of_dpa, OfDpaGroup *group, rocker_tlv_get_le16(group_tlvs[ROCKER_TLV_OF_DPA_GROUP_COUNT]); tlvs = g_new0(RockerTlv *, group->l2_flood.group_count + 1); - if (!tlvs) { - return -ROCKER_ENOMEM; - } g_free(group->l2_flood.group_ids); group->l2_flood.group_ids = g_new0(uint32_t, group->l2_flood.group_count); - if (!group->l2_flood.group_ids) { - err = -ROCKER_ENOMEM; - goto err_out; - } rocker_tlv_parse_nested(tlvs, group->l2_flood.group_count, group_tlvs[ROCKER_TLV_OF_DPA_GROUP_IDS]); @@ -2157,9 +2140,6 @@ static int of_dpa_cmd_group_add(OfDpa *of_dpa, uint32_t group_id, } group = of_dpa_group_alloc(group_id); - if (!group) { - return -ROCKER_ENOMEM; - } err = of_dpa_cmd_group_do(of_dpa, group_id, group, group_tlvs); if (err) { diff --git a/hw/net/rocker/rocker_world.c b/hw/net/rocker/rocker_world.c index 89777e9..f73c534 100644 --- a/hw/net/rocker/rocker_world.c +++ b/hw/net/rocker/rocker_world.c @@ -51,13 +51,11 @@ World *world_alloc(Rocker *r, size_t sizeof_private, { World *w = g_malloc0(sizeof(World) + sizeof_private); - if (w) { - w->r = r; - w->type = type; - w->ops = ops; - if (w->ops->init) { - w->ops->init(w); - } + w->r = r; + w->type = type; + w->ops = ops; + if (w->ops->init) { + w->ops->init(w); } return w; diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c index 671c7e4..3be24bb 100644 --- a/hw/net/rtl8139.c +++ b/hw/net/rtl8139.c @@ -3132,38 +3132,6 @@ static uint32_t rtl8139_io_readl(void *opaque, uint8_t addr) /* */ -static void rtl8139_mmio_writeb(void *opaque, hwaddr addr, uint32_t val) -{ - rtl8139_io_writeb(opaque, addr & 0xFF, val); -} - -static void rtl8139_mmio_writew(void *opaque, hwaddr addr, uint32_t val) -{ - rtl8139_io_writew(opaque, addr & 0xFF, val); -} - -static void rtl8139_mmio_writel(void *opaque, hwaddr addr, uint32_t val) -{ - rtl8139_io_writel(opaque, addr & 0xFF, val); -} - -static uint32_t rtl8139_mmio_readb(void *opaque, hwaddr addr) -{ - return rtl8139_io_readb(opaque, addr & 0xFF); -} - -static uint32_t rtl8139_mmio_readw(void *opaque, hwaddr addr) -{ - uint32_t val = rtl8139_io_readw(opaque, addr & 0xFF); - return val; -} - -static uint32_t rtl8139_mmio_readl(void *opaque, hwaddr addr) -{ - uint32_t val = rtl8139_io_readl(opaque, addr & 0xFF); - return val; -} - static int rtl8139_post_load(void *opaque, int version_id) { RTL8139State* s = opaque; @@ -3344,22 +3312,6 @@ static const MemoryRegionOps rtl8139_io_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static const MemoryRegionOps rtl8139_mmio_ops = { - .old_mmio = { - .read = { - rtl8139_mmio_readb, - rtl8139_mmio_readw, - rtl8139_mmio_readl, - }, - .write = { - rtl8139_mmio_writeb, - rtl8139_mmio_writew, - rtl8139_mmio_writel, - }, - }, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - static void rtl8139_timer(void *opaque) { RTL8139State *s = opaque; @@ -3422,8 +3374,9 @@ static void pci_rtl8139_realize(PCIDevice *dev, Error **errp) memory_region_init_io(&s->bar_io, OBJECT(s), &rtl8139_io_ops, s, "rtl8139", 0x100); - memory_region_init_io(&s->bar_mem, OBJECT(s), &rtl8139_mmio_ops, s, - "rtl8139", 0x100); + memory_region_init_alias(&s->bar_mem, OBJECT(s), "rtl8139-mem", &s->bar_io, + 0, 0x100); + pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->bar_io); pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar_mem); diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h index 639cc07..4f7311b 100644 --- a/include/qemu/sockets.h +++ b/include/qemu/sockets.h @@ -45,7 +45,8 @@ void socket_listen_cleanup(int fd, Error **errp); int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp); /* Old, ipv4 only bits. Don't use for new code. */ -int parse_host_port(struct sockaddr_in *saddr, const char *str); +int parse_host_port(struct sockaddr_in *saddr, const char *str, + Error **errp); int socket_init(void); /** diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h index e6da1a4..d2985b3 100644 --- a/include/sysemu/iothread.h +++ b/include/sysemu/iothread.h @@ -24,6 +24,9 @@ typedef struct { QemuThread thread; AioContext *ctx; + GMainContext *worker_context; + GMainLoop *main_loop; + GOnce once; QemuMutex init_done_lock; QemuCond init_done_cond; /* is thread initialization done? */ bool stopping; @@ -41,5 +44,6 @@ typedef struct { char *iothread_get_id(IOThread *iothread); AioContext *iothread_get_aio_context(IOThread *iothread); void iothread_stop_all(void); +GMainContext *iothread_get_g_main_context(IOThread *iothread); #endif /* IOTHREAD_H */ @@ -57,6 +57,23 @@ static void *iothread_run(void *opaque) while (!atomic_read(&iothread->stopping)) { aio_poll(iothread->ctx, true); + + if (atomic_read(&iothread->worker_context)) { + GMainLoop *loop; + + g_main_context_push_thread_default(iothread->worker_context); + iothread->main_loop = + g_main_loop_new(iothread->worker_context, TRUE); + loop = iothread->main_loop; + + g_main_loop_run(iothread->main_loop); + iothread->main_loop = NULL; + g_main_loop_unref(loop); + + g_main_context_pop_thread_default(iothread->worker_context); + g_main_context_unref(iothread->worker_context); + iothread->worker_context = NULL; + } } rcu_unregister_thread(); @@ -73,6 +90,9 @@ static int iothread_stop(Object *object, void *opaque) } iothread->stopping = true; aio_notify(iothread->ctx); + if (atomic_read(&iothread->main_loop)) { + g_main_loop_quit(iothread->main_loop); + } qemu_thread_join(&iothread->thread); return 0; } @@ -125,6 +145,7 @@ static void iothread_complete(UserCreatable *obj, Error **errp) qemu_mutex_init(&iothread->init_done_lock); qemu_cond_init(&iothread->init_done_cond); + iothread->once = (GOnce) G_ONCE_INIT; /* This assumes we are called from a thread with useful CPU affinity for us * to inherit. @@ -309,3 +330,27 @@ void iothread_stop_all(void) object_child_foreach(container, iothread_stop, NULL); } + +static gpointer iothread_g_main_context_init(gpointer opaque) +{ + AioContext *ctx; + IOThread *iothread = opaque; + GSource *source; + + iothread->worker_context = g_main_context_new(); + + ctx = iothread_get_aio_context(iothread); + source = aio_get_g_source(ctx); + g_source_attach(source, iothread->worker_context); + g_source_unref(source); + + aio_notify(iothread->ctx); + return NULL; +} + +GMainContext *iothread_get_g_main_context(IOThread *iothread) +{ + g_once(&iothread->once, iothread_g_main_context_init, iothread); + + return iothread->worker_context; +} diff --git a/net/colo-compare.c b/net/colo-compare.c index 5fe8e3f..b3f35d7 100644 --- a/net/colo-compare.c +++ b/net/colo-compare.c @@ -29,6 +29,7 @@ #include "qemu/sockets.h" #include "qapi-visit.h" #include "net/colo.h" +#include "sysemu/iothread.h" #define TYPE_COLO_COMPARE "colo-compare" #define COLO_COMPARE(obj) \ @@ -41,27 +42,27 @@ #define REGULAR_PACKET_CHECK_MS 3000 /* - + CompareState ++ - | | - +---------------+ +---------------+ +---------------+ - |conn list +--->conn +--------->conn | - +---------------+ +---------------+ +---------------+ - | | | | | | - +---------------+ +---v----+ +---v----+ +---v----+ +---v----+ - |primary | |secondary |primary | |secondary - |packet | |packet + |packet | |packet + - +--------+ +--------+ +--------+ +--------+ - | | | | - +---v----+ +---v----+ +---v----+ +---v----+ - |primary | |secondary |primary | |secondary - |packet | |packet + |packet | |packet + - +--------+ +--------+ +--------+ +--------+ - | | | | - +---v----+ +---v----+ +---v----+ +---v----+ - |primary | |secondary |primary | |secondary - |packet | |packet + |packet | |packet + - +--------+ +--------+ +--------+ +--------+ -*/ + * + CompareState ++ + * | | + * +---------------+ +---------------+ +---------------+ + * | conn list + - > conn + ------- > conn + -- > ...... + * +---------------+ +---------------+ +---------------+ + * | | | | | | + * +---------------+ +---v----+ +---v----+ +---v----+ +---v----+ + * |primary | |secondary |primary | |secondary + * |packet | |packet + |packet | |packet + + * +--------+ +--------+ +--------+ +--------+ + * | | | | + * +---v----+ +---v----+ +---v----+ +---v----+ + * |primary | |secondary |primary | |secondary + * |packet | |packet + |packet | |packet + + * +--------+ +--------+ +--------+ +--------+ + * | | | | + * +---v----+ +---v----+ +---v----+ +---v----+ + * |primary | |secondary |primary | |secondary + * |packet | |packet + |packet | |packet + + * +--------+ +--------+ +--------+ +--------+ + */ typedef struct CompareState { Object parent; @@ -75,18 +76,17 @@ typedef struct CompareState { SocketReadState sec_rs; bool vnet_hdr; - /* connection list: the connections belonged to this NIC could be found - * in this list. - * element type: Connection + /* + * Record the connection that through the NIC + * Element type: Connection */ GQueue conn_list; - /* hashtable to save connection */ + /* Record the connection without repetition */ GHashTable *connection_track_table; - /* compare thread, a thread for each NIC */ - QemuThread thread; + IOThread *iothread; GMainContext *worker_context; - GMainLoop *compare_loop; + QEMUTimer *packet_check_timer; } CompareState; typedef struct CompareClass { @@ -186,7 +186,10 @@ static int packet_enqueue(CompareState *s, int mode) * return: 0 means packet same * > 0 || < 0 means packet different */ -static int colo_packet_compare_common(Packet *ppkt, Packet *spkt, int offset) +static int colo_packet_compare_common(Packet *ppkt, + Packet *spkt, + int poffset, + int soffset) { if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) { char pri_ip_src[20], pri_ip_dst[20], sec_ip_src[20], sec_ip_dst[20]; @@ -201,12 +204,13 @@ static int colo_packet_compare_common(Packet *ppkt, Packet *spkt, int offset) sec_ip_src, sec_ip_dst); } - offset = ppkt->vnet_hdr_len + offset; + poffset = ppkt->vnet_hdr_len + poffset; + soffset = ppkt->vnet_hdr_len + soffset; - if (ppkt->size == spkt->size) { - return memcmp(ppkt->data + offset, - spkt->data + offset, - spkt->size - offset); + if (ppkt->size - poffset == spkt->size - soffset) { + return memcmp(ppkt->data + poffset, + spkt->data + soffset, + spkt->size - soffset); } else { trace_colo_compare_main("Net packet size are not the same"); return -1; @@ -263,13 +267,22 @@ static int colo_packet_compare_tcp(Packet *spkt, Packet *ppkt) * so we just need skip this field. */ if (ptcp->th_off > 5) { - ptrdiff_t tcp_offset; + ptrdiff_t ptcp_offset, stcp_offset; - tcp_offset = ppkt->transport_header - (uint8_t *)ppkt->data - + (ptcp->th_off * 4) - ppkt->vnet_hdr_len; - res = colo_packet_compare_common(ppkt, spkt, tcp_offset); + ptcp_offset = ppkt->transport_header - (uint8_t *)ppkt->data + + (ptcp->th_off * 4) - ppkt->vnet_hdr_len; + stcp_offset = spkt->transport_header - (uint8_t *)spkt->data + + (stcp->th_off * 4) - spkt->vnet_hdr_len; + + /* + * When network is busy, some tcp options(like sack) will unpredictable + * occur in primary side or secondary side. it will make packet size + * not same, but the two packet's payload is identical. colo just + * care about packet payload, so we skip the option field. + */ + res = colo_packet_compare_common(ppkt, spkt, ptcp_offset, stcp_offset); } else if (ptcp->th_sum == stcp->th_sum) { - res = colo_packet_compare_common(ppkt, spkt, ETH_HLEN); + res = colo_packet_compare_common(ppkt, spkt, ETH_HLEN, ETH_HLEN); } else { res = -1; } @@ -330,6 +343,7 @@ static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt) * the ip payload here. */ ret = colo_packet_compare_common(ppkt, spkt, + network_header_length + ETH_HLEN, network_header_length + ETH_HLEN); if (ret) { @@ -367,6 +381,7 @@ static int colo_packet_compare_icmp(Packet *spkt, Packet *ppkt) * the ip payload here. */ if (colo_packet_compare_common(ppkt, spkt, + network_header_length + ETH_HLEN, network_header_length + ETH_HLEN)) { trace_colo_compare_icmp_miscompare("primary pkt size", ppkt->size); @@ -404,7 +419,7 @@ static int colo_packet_compare_other(Packet *spkt, Packet *ppkt) sec_ip_src, sec_ip_dst); } - return colo_packet_compare_common(ppkt, spkt, 0); + return colo_packet_compare_common(ppkt, spkt, 0, 0); } static int colo_old_packet_check_one(Packet *pkt, int64_t *check_time) @@ -430,8 +445,11 @@ static int colo_old_packet_check_one_conn(Connection *conn, (GCompareFunc)colo_old_packet_check_one); if (result) { - /* do checkpoint will flush old packet */ - /* TODO: colo_notify_checkpoint();*/ + /* Do checkpoint will flush old packet */ + /* + * TODO: Notify colo frame to do checkpoint. + * colo_compare_inconsistent_notify(); + */ return 0; } @@ -469,7 +487,7 @@ static void colo_compare_connection(void *opaque, void *user_data) while (!g_queue_is_empty(&conn->primary_list) && !g_queue_is_empty(&conn->secondary_list)) { - pkt = g_queue_pop_tail(&conn->primary_list); + pkt = g_queue_pop_head(&conn->primary_list); switch (conn->ip_proto) { case IPPROTO_TCP: result = g_queue_find_custom(&conn->secondary_list, @@ -507,7 +525,7 @@ static void colo_compare_connection(void *opaque, void *user_data) * until next comparison. */ trace_colo_compare_main("packet different"); - g_queue_push_tail(&conn->primary_list, pkt); + g_queue_push_head(&conn->primary_list, pkt); /* TODO: colo_notify_checkpoint();*/ break; } @@ -597,22 +615,40 @@ static void compare_sec_chr_in(void *opaque, const uint8_t *buf, int size) * Check old packet regularly so it can watch for any packets * that the secondary hasn't produced equivalents of. */ -static gboolean check_old_packet_regular(void *opaque) +static void check_old_packet_regular(void *opaque) { CompareState *s = opaque; /* if have old packet we will notify checkpoint */ colo_old_packet_check(s); + timer_mod(s->packet_check_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + + REGULAR_PACKET_CHECK_MS); +} - return TRUE; +static void colo_compare_timer_init(CompareState *s) +{ + AioContext *ctx = iothread_get_aio_context(s->iothread); + + s->packet_check_timer = aio_timer_new(ctx, QEMU_CLOCK_VIRTUAL, + SCALE_MS, check_old_packet_regular, + s); + timer_mod(s->packet_check_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + + REGULAR_PACKET_CHECK_MS); } -static void *colo_compare_thread(void *opaque) +static void colo_compare_timer_del(CompareState *s) { - CompareState *s = opaque; - GSource *timeout_source; + if (s->packet_check_timer) { + timer_del(s->packet_check_timer); + timer_free(s->packet_check_timer); + s->packet_check_timer = NULL; + } + } - s->worker_context = g_main_context_new(); +static void colo_compare_iothread(CompareState *s) +{ + object_ref(OBJECT(s->iothread)); + s->worker_context = iothread_get_g_main_context(s->iothread); qemu_chr_fe_set_handlers(&s->chr_pri_in, compare_chr_can_read, compare_pri_chr_in, NULL, NULL, @@ -621,20 +657,7 @@ static void *colo_compare_thread(void *opaque) compare_sec_chr_in, NULL, NULL, s, s->worker_context, true); - s->compare_loop = g_main_loop_new(s->worker_context, FALSE); - - /* To kick any packets that the secondary doesn't match */ - timeout_source = g_timeout_source_new(REGULAR_PACKET_CHECK_MS); - g_source_set_callback(timeout_source, - (GSourceFunc)check_old_packet_regular, s, NULL); - g_source_attach(timeout_source, s->worker_context); - - g_main_loop_run(s->compare_loop); - - g_source_unref(timeout_source); - g_main_loop_unref(s->compare_loop); - g_main_context_unref(s->worker_context); - return NULL; + colo_compare_timer_init(s); } static char *compare_get_pri_indev(Object *obj, Error **errp) @@ -759,12 +782,10 @@ static void colo_compare_complete(UserCreatable *uc, Error **errp) { CompareState *s = COLO_COMPARE(uc); Chardev *chr; - char thread_name[64]; - static int compare_id; - if (!s->pri_indev || !s->sec_indev || !s->outdev) { + if (!s->pri_indev || !s->sec_indev || !s->outdev || !s->iothread) { error_setg(errp, "colo compare needs 'primary_in' ," - "'secondary_in','outdev' property set"); + "'secondary_in','outdev','iothread' property set"); return; } else if (!strcmp(s->pri_indev, s->outdev) || !strcmp(s->sec_indev, s->outdev) || @@ -799,12 +820,7 @@ static void colo_compare_complete(UserCreatable *uc, Error **errp) g_free, connection_destroy); - sprintf(thread_name, "colo-compare %d", compare_id); - qemu_thread_create(&s->thread, thread_name, - colo_compare_thread, s, - QEMU_THREAD_JOINABLE); - compare_id++; - + colo_compare_iothread(s); return; } @@ -848,6 +864,10 @@ static void colo_compare_init(Object *obj) object_property_add_str(obj, "outdev", compare_get_outdev, compare_set_outdev, NULL); + object_property_add_link(obj, "iothread", TYPE_IOTHREAD, + (Object **)&s->iothread, + object_property_allow_set_link, + OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL); s->vnet_hdr = false; object_property_add_bool(obj, "vnet_hdr_support", compare_get_vnet_hdr, @@ -861,16 +881,21 @@ static void colo_compare_finalize(Object *obj) qemu_chr_fe_deinit(&s->chr_pri_in, false); qemu_chr_fe_deinit(&s->chr_sec_in, false); qemu_chr_fe_deinit(&s->chr_out, false); - - g_main_loop_quit(s->compare_loop); - qemu_thread_join(&s->thread); - + if (s->iothread) { + colo_compare_timer_del(s); + } /* Release all unhandled packets after compare thead exited */ g_queue_foreach(&s->conn_list, colo_flush_packets, s); g_queue_clear(&s->conn_list); - g_hash_table_destroy(s->connection_track_table); + if (s->connection_track_table) { + g_hash_table_destroy(s->connection_track_table); + } + + if (s->iothread) { + object_unref(OBJECT(s->iothread)); + } g_free(s->pri_indev); g_free(s->sec_indev); g_free(s->outdev); diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c index 9812009..2be388f 100644 --- a/net/filter-rewriter.c +++ b/net/filter-rewriter.c @@ -99,7 +99,8 @@ static int handle_primary_tcp_pkt(NetFilterState *nf, /* handle packets to the secondary from the primary */ tcp_pkt->th_ack = htonl(ntohl(tcp_pkt->th_ack) + conn->offset); - net_checksum_calculate((uint8_t *)pkt->data, pkt->size); + net_checksum_calculate((uint8_t *)pkt->data + pkt->vnet_hdr_len, + pkt->size - pkt->vnet_hdr_len); } } @@ -138,7 +139,8 @@ static int handle_secondary_tcp_pkt(NetFilterState *nf, /* handle packets to the primary from the secondary*/ tcp_pkt->th_seq = htonl(ntohl(tcp_pkt->th_seq) - conn->offset); - net_checksum_calculate((uint8_t *)pkt->data, pkt->size); + net_checksum_calculate((uint8_t *)pkt->data + pkt->vnet_hdr_len, + pkt->size - pkt->vnet_hdr_len); } } @@ -100,7 +100,8 @@ static int get_str_sep(char *buf, int buf_size, const char **pp, int sep) return 0; } -int parse_host_port(struct sockaddr_in *saddr, const char *str) +int parse_host_port(struct sockaddr_in *saddr, const char *str, + Error **errp) { char buf[512]; struct hostent *he; @@ -108,24 +109,35 @@ int parse_host_port(struct sockaddr_in *saddr, const char *str) int port; p = str; - if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) + if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) { + error_setg(errp, "host address '%s' doesn't contain ':' " + "separating host from port", str); return -1; + } saddr->sin_family = AF_INET; if (buf[0] == '\0') { saddr->sin_addr.s_addr = 0; } else { if (qemu_isdigit(buf[0])) { - if (!inet_aton(buf, &saddr->sin_addr)) + if (!inet_aton(buf, &saddr->sin_addr)) { + error_setg(errp, "host address '%s' is not a valid " + "IPv4 address", buf); return -1; + } } else { - if ((he = gethostbyname(buf)) == NULL) + he = gethostbyname(buf); + if (he == NULL) { + error_setg(errp, "can't resolve host address '%s'", buf); return - 1; + } saddr->sin_addr = *(struct in_addr *)he->h_addr; } } port = strtol(p, (char **)&r, 0); - if (r == p) + if (r == p) { + error_setg(errp, "port number '%s' is invalid", p); return -1; + } saddr->sin_port = htons(port); return 0; } diff --git a/net/socket.c b/net/socket.c index 18af2ab..e6b471c 100644 --- a/net/socket.c +++ b/net/socket.c @@ -209,7 +209,9 @@ static void net_socket_send_dgram(void *opaque) } } -static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr *localaddr) +static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, + struct in_addr *localaddr, + Error **errp) { struct ip_mreq imr; int fd; @@ -221,16 +223,16 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr #endif if (!IN_MULTICAST(ntohl(mcastaddr->sin_addr.s_addr))) { - fprintf(stderr, "qemu: error: specified mcastaddr \"%s\" (0x%08x) " - "does not contain a multicast address\n", - inet_ntoa(mcastaddr->sin_addr), - (int)ntohl(mcastaddr->sin_addr.s_addr)); + error_setg(errp, "specified mcastaddr %s (0x%08x) " + "does not contain a multicast address", + inet_ntoa(mcastaddr->sin_addr), + (int)ntohl(mcastaddr->sin_addr.s_addr)); return -1; - } + fd = qemu_socket(PF_INET, SOCK_DGRAM, 0); if (fd < 0) { - perror("socket(PF_INET, SOCK_DGRAM)"); + error_setg_errno(errp, errno, "can't create datagram socket"); return -1; } @@ -242,13 +244,15 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr val = 1; ret = qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); if (ret < 0) { - perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)"); + error_setg_errno(errp, errno, + "can't set socket option SO_REUSEADDR"); goto fail; } ret = bind(fd, (struct sockaddr *)mcastaddr, sizeof(*mcastaddr)); if (ret < 0) { - perror("bind"); + error_setg_errno(errp, errno, "can't bind ip=%s to socket", + inet_ntoa(mcastaddr->sin_addr)); goto fail; } @@ -263,7 +267,9 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr ret = qemu_setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(struct ip_mreq)); if (ret < 0) { - perror("setsockopt(IP_ADD_MEMBERSHIP)"); + error_setg_errno(errp, errno, + "can't add socket to multicast group %s", + inet_ntoa(imr.imr_multiaddr)); goto fail; } @@ -272,7 +278,8 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr ret = qemu_setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)); if (ret < 0) { - perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)"); + error_setg_errno(errp, errno, + "can't force multicast message to loopback"); goto fail; } @@ -281,7 +288,8 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr ret = qemu_setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, localaddr, sizeof(*localaddr)); if (ret < 0) { - perror("setsockopt(IP_MULTICAST_IF)"); + error_setg_errno(errp, errno, + "can't set the default network send interface"); goto fail; } } @@ -321,7 +329,8 @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer, const char *model, const char *name, int fd, int is_connected, - const char *mcast) + const char *mcast, + Error **errp) { struct sockaddr_in saddr; int newfd; @@ -334,22 +343,17 @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer, */ if (is_connected && mcast != NULL) { - if (parse_host_port(&saddr, mcast) < 0) { - fprintf(stderr, - "qemu: error: init_dgram: fd=%d failed parse_host_port()\n", - fd); + if (parse_host_port(&saddr, mcast, errp) < 0) { goto err; } /* must be bound */ if (saddr.sin_addr.s_addr == 0) { - fprintf(stderr, "qemu: error: init_dgram: fd=%d unbound, " - "cannot setup multicast dst addr\n", fd); + error_setg(errp, "can't setup multicast destination address"); goto err; } /* clone dgram socket */ - newfd = net_socket_mcast_create(&saddr, NULL); + newfd = net_socket_mcast_create(&saddr, NULL, errp); if (newfd < 0) { - /* error already reported by net_socket_mcast_create() */ goto err; } /* clone newfd to fd, close newfd */ @@ -431,26 +435,27 @@ static NetSocketState *net_socket_fd_init_stream(NetClientState *peer, static NetSocketState *net_socket_fd_init(NetClientState *peer, const char *model, const char *name, - int fd, int is_connected, const char *mc) + int fd, int is_connected, + const char *mc, Error **errp) { int so_type = -1, optlen=sizeof(so_type); if(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type, (socklen_t *)&optlen)< 0) { - fprintf(stderr, "qemu: error: getsockopt(SO_TYPE) for fd=%d failed\n", - fd); + error_setg(errp, "can't get socket option SO_TYPE"); closesocket(fd); return NULL; } switch(so_type) { case SOCK_DGRAM: - return net_socket_fd_init_dgram(peer, model, name, fd, is_connected, mc); + return net_socket_fd_init_dgram(peer, model, name, fd, is_connected, + mc, errp); case SOCK_STREAM: 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(peer, model, name, fd, is_connected); + error_report("socket type=%d for fd=%d must be either" + " SOCK_DGRAM or SOCK_STREAM", so_type, fd); + closesocket(fd); } return NULL; } @@ -484,19 +489,21 @@ static void net_socket_accept(void *opaque) static int net_socket_listen_init(NetClientState *peer, const char *model, const char *name, - const char *host_str) + const char *host_str, + Error **errp) { NetClientState *nc; NetSocketState *s; struct sockaddr_in saddr; int fd, ret; - if (parse_host_port(&saddr, host_str) < 0) + if (parse_host_port(&saddr, host_str, errp) < 0) { return -1; + } fd = qemu_socket(PF_INET, SOCK_STREAM, 0); if (fd < 0) { - perror("socket"); + error_setg_errno(errp, errno, "can't create stream socket"); return -1; } qemu_set_nonblock(fd); @@ -505,13 +512,14 @@ static int net_socket_listen_init(NetClientState *peer, ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)); if (ret < 0) { - perror("bind"); + error_setg_errno(errp, errno, "can't bind ip=%s to socket", + inet_ntoa(saddr.sin_addr)); closesocket(fd); return -1; } ret = listen(fd, 0); if (ret < 0) { - perror("listen"); + error_setg_errno(errp, errno, "can't listen on socket"); closesocket(fd); return -1; } @@ -530,18 +538,20 @@ static int net_socket_listen_init(NetClientState *peer, static int net_socket_connect_init(NetClientState *peer, const char *model, const char *name, - const char *host_str) + const char *host_str, + Error **errp) { NetSocketState *s; int fd, connected, ret; struct sockaddr_in saddr; - if (parse_host_port(&saddr, host_str) < 0) + if (parse_host_port(&saddr, host_str, errp) < 0) { return -1; + } fd = qemu_socket(PF_INET, SOCK_STREAM, 0); if (fd < 0) { - perror("socket"); + error_setg_errno(errp, errno, "can't create stream socket"); return -1; } qemu_set_nonblock(fd); @@ -557,7 +567,7 @@ static int net_socket_connect_init(NetClientState *peer, errno == EINVAL) { break; } else { - perror("connect"); + error_setg_errno(errp, errno, "can't connect socket"); closesocket(fd); return -1; } @@ -566,9 +576,11 @@ static int net_socket_connect_init(NetClientState *peer, break; } } - s = net_socket_fd_init(peer, model, name, fd, connected, NULL); - if (!s) + s = net_socket_fd_init(peer, model, name, fd, connected, NULL, errp); + if (!s) { return -1; + } + snprintf(s->nc.info_str, sizeof(s->nc.info_str), "socket: connect to %s:%d", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); @@ -579,31 +591,38 @@ static int net_socket_mcast_init(NetClientState *peer, const char *model, const char *name, const char *host_str, - const char *localaddr_str) + const char *localaddr_str, + Error **errp) { NetSocketState *s; int fd; struct sockaddr_in saddr; struct in_addr localaddr, *param_localaddr; - if (parse_host_port(&saddr, host_str) < 0) + if (parse_host_port(&saddr, host_str, errp) < 0) { return -1; + } if (localaddr_str != NULL) { - if (inet_aton(localaddr_str, &localaddr) == 0) + if (inet_aton(localaddr_str, &localaddr) == 0) { + error_setg(errp, "localaddr '%s' is not a valid IPv4 address", + localaddr_str); return -1; + } param_localaddr = &localaddr; } else { param_localaddr = NULL; } - fd = net_socket_mcast_create(&saddr, param_localaddr); - if (fd < 0) + fd = net_socket_mcast_create(&saddr, param_localaddr, errp); + if (fd < 0) { return -1; + } - s = net_socket_fd_init(peer, model, name, fd, 0, NULL); - if (!s) + s = net_socket_fd_init(peer, model, name, fd, 0, NULL, errp); + if (!s) { return -1; + } s->dgram_dst = saddr; @@ -618,40 +637,44 @@ static int net_socket_udp_init(NetClientState *peer, const char *model, const char *name, const char *rhost, - const char *lhost) + const char *lhost, + Error **errp) { NetSocketState *s; int fd, ret; struct sockaddr_in laddr, raddr; - if (parse_host_port(&laddr, lhost) < 0) { + if (parse_host_port(&laddr, lhost, errp) < 0) { return -1; } - if (parse_host_port(&raddr, rhost) < 0) { + if (parse_host_port(&raddr, rhost, errp) < 0) { return -1; } fd = qemu_socket(PF_INET, SOCK_DGRAM, 0); if (fd < 0) { - perror("socket(PF_INET, SOCK_DGRAM)"); + error_setg_errno(errp, errno, "can't create datagram socket"); return -1; } ret = socket_set_fast_reuse(fd); if (ret < 0) { + error_setg_errno(errp, errno, + "can't set socket option SO_REUSEADDR"); closesocket(fd); return -1; } ret = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr)); if (ret < 0) { - perror("bind"); + error_setg_errno(errp, errno, "can't bind ip=%s to socket", + inet_ntoa(laddr.sin_addr)); closesocket(fd); return -1; } qemu_set_nonblock(fd); - s = net_socket_fd_init(peer, model, name, fd, 0, NULL); + s = net_socket_fd_init(peer, model, name, fd, 0, NULL, errp); if (!s) { return -1; } @@ -667,8 +690,6 @@ static int net_socket_udp_init(NetClientState *peer, int net_init_socket(const Netdev *netdev, const char *name, NetClientState *peer, Error **errp) { - /* FIXME error_setg(errp, ...) on failure */ - Error *err = NULL; const NetdevSocketOptions *sock; assert(netdev->type == NET_CLIENT_DRIVER_SOCKET); @@ -676,41 +697,42 @@ int net_init_socket(const Netdev *netdev, const char *name, if (sock->has_listen + sock->has_connect + sock->has_mcast + sock->has_udp > 1) { - error_report("exactly one of listen=, connect=, mcast= or udp=" - " is required"); + error_setg(errp, "exactly one of listen=, connect=, mcast= or udp=" + " is required"); return -1; } if (sock->has_localaddr && !sock->has_mcast && !sock->has_udp) { - error_report("localaddr= is only valid with mcast= or udp="); + error_setg(errp, "localaddr= is only valid with mcast= or udp="); return -1; } if (sock->has_fd) { int fd; - fd = monitor_fd_param(cur_mon, sock->fd, &err); + fd = monitor_fd_param(cur_mon, sock->fd, errp); if (fd == -1) { - error_report_err(err); return -1; } qemu_set_nonblock(fd); - if (!net_socket_fd_init(peer, "socket", name, fd, 1, sock->mcast)) { + if (!net_socket_fd_init(peer, "socket", name, fd, 1, sock->mcast, + errp)) { return -1; } return 0; } if (sock->has_listen) { - if (net_socket_listen_init(peer, "socket", name, sock->listen) == -1) { + if (net_socket_listen_init(peer, "socket", name, sock->listen, errp) + < 0) { return -1; } return 0; } if (sock->has_connect) { - if (net_socket_connect_init(peer, "socket", name, sock->connect) == - -1) { + if (net_socket_connect_init(peer, "socket", name, sock->connect, errp) + < 0) { return -1; } return 0; @@ -720,7 +742,7 @@ int net_init_socket(const Netdev *netdev, const char *name, /* if sock->localaddr is missing, it has been initialized to "all bits * zero" */ if (net_socket_mcast_init(peer, "socket", name, sock->mcast, - sock->localaddr) == -1) { + sock->localaddr, errp) < 0) { return -1; } return 0; @@ -728,11 +750,11 @@ int net_init_socket(const Netdev *netdev, const char *name, assert(sock->has_udp); if (!sock->has_localaddr) { - error_report("localaddr= is mandatory with udp="); + error_setg(errp, "localaddr= is mandatory with udp="); return -1; } - if (net_socket_udp_init(peer, "socket", name, sock->udp, sock->localaddr) == - -1) { + if (net_socket_udp_init(peer, "socket", name, sock->udp, sock->localaddr, + errp) < 0) { return -1; } return 0; |