From 6ce310b5356abb7edc3aa8b8b097d0b8cc76f83f Mon Sep 17 00:00:00 2001 From: Zhang Chen Date: Fri, 28 Jul 2017 18:03:10 +0800 Subject: [PATCH 01/18] net/filter-rewriter.c: Fix rewirter checksum bug when use virtio-net Because vnet_hdr have a offset to net packet, we must add it when use virtio-net. Signed-off-by: Zhang Chen Signed-off-by: Jason Wang --- net/filter-rewriter.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c index 98120095de..2be388f539 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); } } From 107e4b352cc309f9bd7588ef1a44549200620078 Mon Sep 17 00:00:00 2001 From: Mao Zhongyi Date: Mon, 14 Aug 2017 11:33:07 +0800 Subject: [PATCH 02/18] net/rocker: Remove the dead error handling Memory allocation functions like world_alloc, desc_ring_alloc etc, they are all wrappers around g_malloc, g_new etc. But g_malloc and similar functions doesn't return null. Because they ignore the fact that g_malloc() of 0 bytes returns null. So error checks for these allocation failure are superfluous. Now, remove them entirely. Cc: jasowang@redhat.com Cc: jiri@resnulli.us Cc: armbru@redhat.com Cc: f4bug@amsat.org Signed-off-by: Mao Zhongyi Reviewed-by: Markus Armbruster Signed-off-by: Jason Wang --- hw/net/rocker/rocker.c | 47 +---------------------------------- hw/net/rocker/rocker_desc.c | 10 -------- hw/net/rocker/rocker_fp.c | 4 --- hw/net/rocker/rocker_of_dpa.c | 20 --------------- hw/net/rocker/rocker_world.c | 12 ++++----- 5 files changed, 6 insertions(+), 87 deletions(-) diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c index 4f0f6d71e5..7496752649 100644 --- a/hw/net/rocker/rocker.c +++ b/hw/net/rocker/rocker.c @@ -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); @@ -1310,13 +1297,6 @@ 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])); } @@ -1393,9 +1373,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 +1384,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,10 +1406,6 @@ 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); } @@ -1446,25 +1414,12 @@ static int pci_rocker_init(PCIDevice *dev) return 0; -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_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]); diff --git a/hw/net/rocker/rocker_desc.c b/hw/net/rocker/rocker_desc.c index 6184c40f72..b009da4f89 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 1305ac36cc..4b3c9847db 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 9b1e0d2441..191a58e0a7 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 89777e9684..f73c5340ed 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; From 1343a107e46feed8b901bf08ad8485bd5f302912 Mon Sep 17 00:00:00 2001 From: Mao Zhongyi Date: Mon, 14 Aug 2017 11:33:08 +0800 Subject: [PATCH 03/18] net/rocker: Plug memory leak in pci_rocker_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pci_rocker_init() leaks a World when the name more than 9 chars, then return a negative value directly, doesn't make a correct cleanup. So add a new goto label to fix it. Cc: jasowang@redhat.com Cc: jiri@resnulli.us Cc: armbru@redhat.com Cc: f4bug@amsat.org Signed-off-by: Mao Zhongyi Reviewed-by: Markus Armbruster Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Jason Wang --- hw/net/rocker/rocker.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c index 7496752649..9a538a9ccb 100644 --- a/hw/net/rocker/rocker.c +++ b/hw/net/rocker/rocker.c @@ -1355,7 +1355,8 @@ static int pci_rocker_init(PCIDevice *dev) fprintf(stderr, "rocker: name too long; please shorten to at most %d chars\n", MAX_ROCKER_NAME_LEN); - return -EINVAL; + err = -EINVAL; + goto err_name_too_long; } if (memcmp(&r->fp_start_macaddr, &zero, sizeof(zero)) == 0) { @@ -1414,6 +1415,7 @@ static int pci_rocker_init(PCIDevice *dev) return 0; +err_name_too_long: err_duplicate: rocker_msix_uninit(r); err_msix_init: From 0c8f86ea98945678622c6e4b070c4218a53a0d19 Mon Sep 17 00:00:00 2001 From: Mao Zhongyi Date: Mon, 14 Aug 2017 11:33:09 +0800 Subject: [PATCH 04/18] net/rocker: Convert to realize() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The rocker device still implements the old PCIDeviceClass .init() instead of the new .realize(). All devices need to be converted to .realize(). .init() reports errors with fprintf() and return 0 on success, negative number on failure. Meanwhile, when -device rocker fails, it first report a specific error, then a generic one, like this: $ x86_64-softmmu/qemu-system-x86_64 -device rocker,name=qemu-rocker rocker: name too long; please shorten to at most 9 chars qemu-system-x86_64: -device rocker,name=qemu-rocker: Device initialization failed Now, convert it to .realize() that passes errors to its callers via its errp argument. Also avoid the superfluous second error message. After the patch, effect like this: $ x86_64-softmmu/qemu-system-x86_64 -device rocker,name=qemu-rocker qemu-system-x86_64: -device rocker,name=qemu-rocker: name too long; please shorten to at most 9 chars Cc: jasowang@redhat.com Cc: jiri@resnulli.us Cc: armbru@redhat.com Cc: f4bug@amsat.org Signed-off-by: Mao Zhongyi Reviewed-by: Markus Armbruster Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Jason Wang --- hw/net/rocker/rocker.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c index 9a538a9ccb..bb38cba0cb 100644 --- a/hw/net/rocker/rocker.c +++ b/hw/net/rocker/rocker.c @@ -1236,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; } @@ -1285,7 +1283,7 @@ 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); const MACAddr zero = { .a = { 0, 0, 0, 0, 0, 0 } }; @@ -1303,10 +1301,9 @@ static int pci_rocker_init(PCIDevice *dev) 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; } @@ -1326,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; } @@ -1338,7 +1335,7 @@ static int pci_rocker_init(PCIDevice *dev) } if (rocker_find(r->name)) { - err = -EEXIST; + error_setg(errp, "%s already exists", r->name); goto err_duplicate; } @@ -1352,10 +1349,9 @@ 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); - err = -EINVAL; goto err_name_too_long; } @@ -1413,7 +1409,7 @@ static int pci_rocker_init(PCIDevice *dev) QLIST_INSERT_HEAD(&rockers, r, next); - return 0; + return; err_name_too_long: err_duplicate: @@ -1427,7 +1423,6 @@ err_world_type_by_name: world_free(r->worlds[i]); } } - return err; } static void pci_rocker_uninit(PCIDevice *dev) @@ -1512,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; From ac7bc031408491cf17da0a46e3fe34e34a1c1b85 Mon Sep 17 00:00:00 2001 From: Mao Zhongyi Date: Mon, 14 Aug 2017 11:33:10 +0800 Subject: [PATCH 05/18] net/rocker: Fix the unusual macro name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: jasowang@redhat.com Cc: jiri@resnulli.us Cc: armbru@redhat.com Cc: f4bug@amsat.org Suggested-by: Markus Armbruster Signed-off-by: Mao Zhongyi Reviewed-by: Markus Armbruster Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Jason Wang --- hw/net/rocker/rocker.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c index bb38cba0cb..9273473d59 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; @@ -1285,7 +1285,7 @@ static World *rocker_world_type_by_name(Rocker *r, const char *name) 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; @@ -1331,7 +1331,7 @@ static void pci_rocker_realize(PCIDevice *dev, Error **errp) /* validate switch properties */ if (!r->name) { - r->name = g_strdup(ROCKER); + r->name = g_strdup(TYPE_ROCKER); } if (rocker_find(r->name)) { @@ -1427,7 +1427,7 @@ err_world_type_by_name: static void pci_rocker_uninit(PCIDevice *dev) { - Rocker *r = to_rocker(dev); + Rocker *r = ROCKER(dev); int i; QLIST_REMOVE(r, next); @@ -1460,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++) { @@ -1498,7 +1498,7 @@ static Property rocker_properties[] = { }; static const VMStateDescription rocker_vmsd = { - .name = ROCKER, + .name = TYPE_ROCKER, .unmigratable = 1, }; @@ -1521,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, From 726ec828bdc186b98379b1d4dc5942aadfcdda52 Mon Sep 17 00:00:00 2001 From: Matt Parker Date: Tue, 15 Aug 2017 21:06:07 +0100 Subject: [PATCH 06/18] net: rtl8139: do not use old_mmio accesses Both io and memory use the same mmio functions in the rtl8139 device. This patch removes the separate MemoryRegionOps and old_mmio accessors for memory, and replaces it with an alias to the io memory region. Signed-off-by: Matt Parker Signed-off-by: Jason Wang --- hw/net/rtl8139.c | 53 +++--------------------------------------------- 1 file changed, 3 insertions(+), 50 deletions(-) diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c index 671c7e48c6..3be24bbee7 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); From b38576cd020c3192d06aeabb6090d9f0d2b6d664 Mon Sep 17 00:00:00 2001 From: Zhang Chen Date: Wed, 23 Aug 2017 16:51:57 +0800 Subject: [PATCH 07/18] MAINTAINERS: Update mail address for COLO Proxy My Fujitsu mail account will be disabled soon, update the mail info to my private mail. Signed-off-by: Zhang Chen Signed-off-by: Jason Wang --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index caf7e8aca8..36eeb42d19 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1577,7 +1577,7 @@ F: include/migration/failover.h F: docs/COLO-FT.txt COLO Proxy -M: Zhang Chen +M: Zhang Chen M: Li Zhijian S: Supported F: docs/colo-proxy.txt From e1b24b649a8dbd941488402b719a81618980a3c0 Mon Sep 17 00:00:00 2001 From: Mao Zhongyi Date: Mon, 4 Sep 2017 22:35:37 +0800 Subject: [PATCH 08/18] net/socket: Don't treat odd socket type as SOCK_STREAM In net_socket_fd_init(), the 'default' case is odd: it warns, then continues as if the socket type was SOCK_STREAM. The comment explains "this could be a eg. a pty", but that makes no sense. If @fd really was a pty, getsockopt() would fail with ENOTSOCK. If @fd was a socket, but neither SOCK_DGRAM nor SOCK_STREAM. It should not be treated as if it was SOCK_STREAM. Turn this case into an Error. If there is a genuine reason to support something like SOCK_RAW, it should be explicitly handled. Cc: jasowang@redhat.com Cc: armbru@redhat.com Cc: berrange@redhat.com Cc: armbru@redhat.com Cc: eblake@redhat.com Suggested-by: Markus Armbruster Suggested-by: Daniel P. Berrange Signed-off-by: Mao Zhongyi Reviewed-by: Markus Armbruster Signed-off-by: Jason Wang --- net/socket.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/socket.c b/net/socket.c index 18af2ab5f3..b4c5a042a9 100644 --- a/net/socket.c +++ b/net/socket.c @@ -448,9 +448,9 @@ static NetSocketState *net_socket_fd_init(NetClientState *peer, 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; } From c37f0bb1d0d24e3a6b5f4659bb305913dcb798a6 Mon Sep 17 00:00:00 2001 From: Mao Zhongyi Date: Mon, 4 Sep 2017 22:35:38 +0800 Subject: [PATCH 09/18] net/socket: Convert several helper functions to Error Currently, net_socket_mcast_create(), net_socket_fd_init_dgram() and net_socket_fd_init() use the function such as fprintf(), perror() to report an error message. Now, convert these functions to Error. Cc: jasowang@redhat.com Cc: armbru@redhat.com Cc: berrange@redhat.com Signed-off-by: Mao Zhongyi Reviewed-by: Daniel P. Berrange Reviewed-by: Markus Armbruster Signed-off-by: Jason Wang --- net/socket.c | 82 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 32 deletions(-) diff --git a/net/socket.c b/net/socket.c index b4c5a042a9..00f9796d5d 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; @@ -335,21 +344,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); + error_setg(errp, "fd=%d failed parse_host_port()", fd); 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,20 +436,21 @@ 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: @@ -535,6 +541,7 @@ static int net_socket_connect_init(NetClientState *peer, NetSocketState *s; int fd, connected, ret; struct sockaddr_in saddr; + Error *err = NULL; if (parse_host_port(&saddr, host_str) < 0) return -1; @@ -566,9 +573,12 @@ 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, &err); + if (!s) { + error_report_err(err); 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)); @@ -585,6 +595,7 @@ static int net_socket_mcast_init(NetClientState *peer, int fd; struct sockaddr_in saddr; struct in_addr localaddr, *param_localaddr; + Error *err = NULL; if (parse_host_port(&saddr, host_str) < 0) return -1; @@ -597,13 +608,17 @@ static int net_socket_mcast_init(NetClientState *peer, param_localaddr = NULL; } - fd = net_socket_mcast_create(&saddr, param_localaddr); - if (fd < 0) + fd = net_socket_mcast_create(&saddr, param_localaddr, &err); + if (fd < 0) { + error_report_err(err); 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, &err); + if (!s) { + error_report_err(err); return -1; + } s->dgram_dst = saddr; @@ -623,6 +638,7 @@ static int net_socket_udp_init(NetClientState *peer, NetSocketState *s; int fd, ret; struct sockaddr_in laddr, raddr; + Error *err = NULL; if (parse_host_port(&laddr, lhost) < 0) { return -1; @@ -651,8 +667,9 @@ static int net_socket_udp_init(NetClientState *peer, } 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, &err); if (!s) { + error_report_err(err); return -1; } @@ -695,7 +712,8 @@ int net_init_socket(const Netdev *netdev, const char *name, 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; From bcd4dfd6852361361d6622de7e67f94e2b475d27 Mon Sep 17 00:00:00 2001 From: Mao Zhongyi Date: Mon, 4 Sep 2017 22:35:39 +0800 Subject: [PATCH 10/18] net/net: Convert parse_host_port() to Error Cc: berrange@redhat.com Cc: kraxel@redhat.com Cc: pbonzini@redhat.com Cc: jasowang@redhat.com Cc: armbru@redhat.com Cc: eblake@redhat.com Signed-off-by: Mao Zhongyi Reviewed-by: Markus Armbruster Signed-off-by: Jason Wang --- include/qemu/sockets.h | 3 ++- net/net.c | 22 +++++++++++++++++----- net/socket.c | 22 +++++++++++++++------- 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h index 639cc079d9..4f7311b52a 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/net/net.c b/net/net.c index 2fa99c0497..bebb042b74 100644 --- a/net/net.c +++ b/net/net.c @@ -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 00f9796d5d..12495d1ce8 100644 --- a/net/socket.c +++ b/net/socket.c @@ -343,8 +343,7 @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer, */ if (is_connected && mcast != NULL) { - if (parse_host_port(&saddr, mcast) < 0) { - error_setg(errp, "fd=%d failed parse_host_port()", fd); + if (parse_host_port(&saddr, mcast, errp) < 0) { goto err; } /* must be bound */ @@ -496,9 +495,12 @@ static int net_socket_listen_init(NetClientState *peer, NetSocketState *s; struct sockaddr_in saddr; int fd, ret; + Error *err = NULL; - if (parse_host_port(&saddr, host_str) < 0) + if (parse_host_port(&saddr, host_str, &err) < 0) { + error_report_err(err); return -1; + } fd = qemu_socket(PF_INET, SOCK_STREAM, 0); if (fd < 0) { @@ -543,8 +545,10 @@ static int net_socket_connect_init(NetClientState *peer, struct sockaddr_in saddr; Error *err = NULL; - if (parse_host_port(&saddr, host_str) < 0) + if (parse_host_port(&saddr, host_str, &err) < 0) { + error_report_err(err); return -1; + } fd = qemu_socket(PF_INET, SOCK_STREAM, 0); if (fd < 0) { @@ -597,8 +601,10 @@ static int net_socket_mcast_init(NetClientState *peer, struct in_addr localaddr, *param_localaddr; Error *err = NULL; - if (parse_host_port(&saddr, host_str) < 0) + if (parse_host_port(&saddr, host_str, &err) < 0) { + error_report_err(err); return -1; + } if (localaddr_str != NULL) { if (inet_aton(localaddr_str, &localaddr) == 0) @@ -640,11 +646,13 @@ static int net_socket_udp_init(NetClientState *peer, struct sockaddr_in laddr, raddr; Error *err = NULL; - if (parse_host_port(&laddr, lhost) < 0) { + if (parse_host_port(&laddr, lhost, &err) < 0) { + error_report_err(err); return -1; } - if (parse_host_port(&raddr, rhost) < 0) { + if (parse_host_port(&raddr, rhost, &err) < 0) { + error_report_err(err); return -1; } From 0522a959aec29768610900636f6234ab40530f82 Mon Sep 17 00:00:00 2001 From: Mao Zhongyi Date: Mon, 4 Sep 2017 22:35:40 +0800 Subject: [PATCH 11/18] net/socket: Improve -net socket error reporting When -net socket fails, it first reports a specific error, then a generic one, like this: $ ./x86_64-softmmu/qemu-system-x86_64 -net socket,mcast=230.0.0.1:1234,listen qemu-system-x86_64: -net socket,mcast=230.0.0.1:1234,listen: exactly one of listen=, connect=, mcast= or udp= is required qemu-system-x86_64: -net socket,mcast=230.0.0.1:1234,listen: Device 'socket' could not be initialized Convert net_socket_*_init() to Error to get rid of the superfluous second error message. After the patch, the effect like this: $ ./x86_64-softmmu/qemu-system-x86_64 -net socket,mcast=230.0.0.1:1234,listen qemu-system-x86_64: -net socket,mcast=230.0.0.1:1234,listen: exactly one of listen=, connect=, mcast= or udp= is requireda This also fixes a few silent failures to report an error. Cc: jasowang@redhat.com Cc: armbru@redhat.com Cc: berrange@redhat.com Signed-off-by: Mao Zhongyi Reviewed-by: Markus Armbruster Signed-off-by: Jason Wang --- net/socket.c | 92 +++++++++++++++++++++++++--------------------------- 1 file changed, 44 insertions(+), 48 deletions(-) diff --git a/net/socket.c b/net/socket.c index 12495d1ce8..e6b471c63d 100644 --- a/net/socket.c +++ b/net/socket.c @@ -489,22 +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; - Error *err = NULL; - if (parse_host_port(&saddr, host_str, &err) < 0) { - error_report_err(err); + 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); @@ -513,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; } @@ -538,21 +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; - Error *err = NULL; - if (parse_host_port(&saddr, host_str, &err) < 0) { - error_report_err(err); + 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); @@ -568,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; } @@ -577,9 +576,8 @@ static int net_socket_connect_init(NetClientState *peer, break; } } - s = net_socket_fd_init(peer, model, name, fd, connected, NULL, &err); + s = net_socket_fd_init(peer, model, name, fd, connected, NULL, errp); if (!s) { - error_report_err(err); return -1; } @@ -593,36 +591,36 @@ 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; - Error *err = NULL; - if (parse_host_port(&saddr, host_str, &err) < 0) { - error_report_err(err); + 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, &err); + fd = net_socket_mcast_create(&saddr, param_localaddr, errp); if (fd < 0) { - error_report_err(err); return -1; } - s = net_socket_fd_init(peer, model, name, fd, 0, NULL, &err); + s = net_socket_fd_init(peer, model, name, fd, 0, NULL, errp); if (!s) { - error_report_err(err); return -1; } @@ -639,45 +637,45 @@ 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; - Error *err = NULL; - if (parse_host_port(&laddr, lhost, &err) < 0) { - error_report_err(err); + if (parse_host_port(&laddr, lhost, errp) < 0) { return -1; } - if (parse_host_port(&raddr, rhost, &err) < 0) { - error_report_err(err); + 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, &err); + s = net_socket_fd_init(peer, model, name, fd, 0, NULL, errp); if (!s) { - error_report_err(err); return -1; } @@ -692,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); @@ -701,22 +697,21 @@ 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); @@ -728,15 +723,16 @@ int net_init_socket(const Netdev *netdev, const char *name, } 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; @@ -746,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; @@ -754,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; From 757704f1b7bffd441101bdab0bbcff27cd11ab34 Mon Sep 17 00:00:00 2001 From: Kamil Rytarowski Date: Sun, 3 Sep 2017 18:37:26 +0200 Subject: [PATCH 12/18] e1000: Rename the SEC symbol to SEQEC SunOS defines SEC in as 1 (commonly used time symbols). This fixes build on SmartOS (Joyent). Patch cherry-picked from pkgsrc by jperkin (Joyent). Signed-off-by: Kamil Rytarowski Reviewed-by: Dmitry Fleytman Signed-off-by: Jason Wang --- hw/net/e1000.c | 4 ++-- hw/net/e1000_regs.h | 2 +- hw/net/e1000e_core.c | 2 +- hw/net/e1000x_common.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/net/e1000.c b/hw/net/e1000.c index f2e5072d27..eebe3a9c13 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 23eed50b9c..ae99f58bab 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 81405640f0..43a8d89955 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 21bf28e0cc..3072ce9d50 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), From 6f5009c38cafad883212810a2219479a8ff408c0 Mon Sep 17 00:00:00 2001 From: Zhang Chen Date: Tue, 5 Sep 2017 14:31:04 +0800 Subject: [PATCH 13/18] net/colo-compare.c: Optimize unpredictable tcp options comparison 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. Signed-off-by: Zhang Chen Signed-off-by: Jason Wang --- net/colo-compare.c | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/net/colo-compare.c b/net/colo-compare.c index 5fe8e3fad9..612fbac72c 100644 --- a/net/colo-compare.c +++ b/net/colo-compare.c @@ -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) From 626bba988af8f38b2820f60cfdf5a27bcb74123b Mon Sep 17 00:00:00 2001 From: Zhang Chen Date: Tue, 5 Sep 2017 14:31:05 +0800 Subject: [PATCH 14/18] net/colo-compare.c: Adjust net queue pop order for performance The packet_enqueue() use g_queue_push_tail() to enqueue net packet, so it is more efficent way use g_queue_pop_head() to get packet for compare. That will improve the success rate of comparison. In my test the performance of ftp put 1000M file will increase 10% Signed-off-by: Zhang Chen Signed-off-by: Jason Wang --- net/colo-compare.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/colo-compare.c b/net/colo-compare.c index 612fbac72c..f480315753 100644 --- a/net/colo-compare.c +++ b/net/colo-compare.c @@ -484,7 +484,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, @@ -522,7 +522,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; } From 61c5f46959ee74d6dabd0ee648ca555932f91955 Mon Sep 17 00:00:00 2001 From: Zhang Chen Date: Tue, 5 Sep 2017 14:31:06 +0800 Subject: [PATCH 15/18] net/colo-compare.c: Fix comments and scheme Signed-off-by: Zhang Chen Signed-off-by: Jason Wang --- net/colo-compare.c | 59 ++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/net/colo-compare.c b/net/colo-compare.c index f480315753..eee33b87a8 100644 --- a/net/colo-compare.c +++ b/net/colo-compare.c @@ -41,27 +41,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,14 +75,14 @@ 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 */ + /* This thread just do packet compare job */ QemuThread thread; GMainContext *worker_context; @@ -445,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; } From 329163cbe64a615b4edf6c40f2fff8c79dbc8fb4 Mon Sep 17 00:00:00 2001 From: Wang Yong Date: Tue, 29 Aug 2017 15:22:37 +0800 Subject: [PATCH 16/18] qemu-iothread: IOThread supports the GMainContext event loop IOThread uses AioContext event loop and does not run a GMainContext. Therefore,chardev cannot work in IOThread,such as the chardev is used for colo-compare packets reception. This patch makes the IOThread run the GMainContext event loop, chardev and IOThread can work together. Reviewed-by: Fam Zheng Signed-off-by: Wang Yong Signed-off-by: Wang Guang Signed-off-by: Jason Wang --- include/sysemu/iothread.h | 4 ++++ iothread.c | 45 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h index e6da1a4087..d2985b30ba 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 */ diff --git a/iothread.c b/iothread.c index beeb870534..44c8944dc4 100644 --- a/iothread.c +++ b/iothread.c @@ -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; +} From dd321ecfc2e82e6f9578b986060b1aa3f036bd98 Mon Sep 17 00:00:00 2001 From: Wang Yong Date: Tue, 29 Aug 2017 15:22:38 +0800 Subject: [PATCH 17/18] colo-compare: Use IOThread to Check old packet regularly and Process pactkets of the primary Remove the task which check old packet in the comparing thread, then use IOthread context timer to handle it. Process pactkets in the IOThread which arrived over the socket. we use iothread_get_g_main_context to create a new g_main_loop in the IOThread.then the packets from the primary and the secondary are processed in the IOThread. Finally remove the colo-compare thread using the IOThread instead. Reviewed-by: Zhang Chen Signed-off-by: Wang Yong Signed-off-by: Wang Guang Signed-off-by: Jason Wang --- net/colo-compare.c | 85 +++++++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 39 deletions(-) diff --git a/net/colo-compare.c b/net/colo-compare.c index eee33b87a8..b3f35d729a 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) \ @@ -82,11 +83,10 @@ typedef struct CompareState { GQueue conn_list; /* Record the connection without repetition */ GHashTable *connection_track_table; - /* This thread just do packet compare job */ - QemuThread thread; + IOThread *iothread; GMainContext *worker_context; - GMainLoop *compare_loop; + QEMUTimer *packet_check_timer; } CompareState; typedef struct CompareClass { @@ -615,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); - - return TRUE; + 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_init(CompareState *s) { - CompareState *s = opaque; - GSource *timeout_source; + AioContext *ctx = iothread_get_aio_context(s->iothread); - s->worker_context = g_main_context_new(); + 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_timer_del(CompareState *s) +{ + if (s->packet_check_timer) { + timer_del(s->packet_check_timer); + timer_free(s->packet_check_timer); + s->packet_check_timer = NULL; + } + } + +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, @@ -639,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) @@ -777,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) || @@ -817,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; } @@ -866,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, @@ -879,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); From 861d51e62bb197b43606f888dbefbabebaf0d854 Mon Sep 17 00:00:00 2001 From: Wang Yong Date: Tue, 29 Aug 2017 15:22:39 +0800 Subject: [PATCH 18/18] colo-compare: Update the COLO document to add the IOThread configuration Update colo-proxy.txt,add IOThread configuration. Later we have to configure IOThread,if not COLO can not work. Reviewed-by: Zhang Chen Signed-off-by: Wang Yong Signed-off-by: Wang Guang Signed-off-by: Jason Wang --- docs/colo-proxy.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/colo-proxy.txt b/docs/colo-proxy.txt index f6a624fb8a..8b726ea094 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