1
The following changes since commit cda4a338c4243fa3bff4498b935340ac7121cc76:
1
The following changes since commit 7dd9d7e0bd29abf590d1ac235c0a00606ef81153:
2
2
3
tcg/tci: Add TCG_TARGET_DEFAULT_MO (2017-09-07 18:57:34 +0100)
3
Merge tag 'pull-ppc-20220831' of https://gitlab.com/danielhb/qemu into staging (2022-09-01 13:53:20 -0400)
4
4
5
are available in the git repository at:
5
are available in the git repository at:
6
6
7
https://github.com/jasowang/qemu.git tags/net-pull-request
7
https://github.com/jasowang/qemu.git tags/net-pull-request
8
8
9
for you to fetch changes up to 861d51e62bb197b43606f888dbefbabebaf0d854:
9
for you to fetch changes up to 36a894aeb64a2e02871016da1c37d4a4ca109182:
10
10
11
colo-compare: Update the COLO document to add the IOThread configuration (2017-09-08 09:34:40 +0800)
11
net: tulip: Restrict DMA engine to memories (2022-09-02 10:22:39 +0800)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
14
15
----------------------------------------------------------------
15
----------------------------------------------------------------
16
Kamil Rytarowski (1):
16
Eugenio Pérez (19):
17
e1000: Rename the SEC symbol to SEQEC
17
vdpa: Skip the maps not in the iova tree
18
vdpa: do not save failed dma maps in SVQ iova tree
19
util: accept iova_tree_remove_parameter by value
20
vdpa: Remove SVQ vring from iova_tree at shutdown
21
vdpa: Make SVQ vring unmapping return void
22
vhost: Always store new kick fd on vhost_svq_set_svq_kick_fd
23
vdpa: Use ring hwaddr at vhost_vdpa_svq_unmap_ring
24
vhost: stop transfer elem ownership in vhost_handle_guest_kick
25
vhost: use SVQ element ndescs instead of opaque data for desc validation
26
vhost: Delete useless read memory barrier
27
vhost: Do not depend on !NULL VirtQueueElement on vhost_svq_flush
28
vhost_net: Add NetClientInfo start callback
29
vhost_net: Add NetClientInfo stop callback
30
vdpa: add net_vhost_vdpa_cvq_info NetClientInfo
31
vdpa: Move command buffers map to start of net device
32
vdpa: extract vhost_vdpa_net_cvq_add from vhost_vdpa_net_handle_ctrl_avail
33
vhost_net: add NetClientState->load() callback
34
vdpa: Add virtio-net mac address via CVQ at start
35
vdpa: Delete CVQ migration blocker
18
36
19
Mao Zhongyi (8):
37
Zhang Chen (1):
20
net/rocker: Remove the dead error handling
38
net/colo.c: Fix the pointer issue reported by Coverity.
21
net/rocker: Plug memory leak in pci_rocker_init()
22
net/rocker: Convert to realize()
23
net/rocker: Fix the unusual macro name
24
net/socket: Don't treat odd socket type as SOCK_STREAM
25
net/socket: Convert several helper functions to Error
26
net/net: Convert parse_host_port() to Error
27
net/socket: Improve -net socket error reporting
28
39
29
Matt Parker (1):
40
Zheyu Ma (1):
30
net: rtl8139: do not use old_mmio accesses
41
net: tulip: Restrict DMA engine to memories
31
42
32
Wang Yong (3):
43
hw/i386/intel_iommu.c | 6 +-
33
qemu-iothread: IOThread supports the GMainContext event loop
44
hw/net/tulip.c | 4 +-
34
colo-compare: Use IOThread to Check old packet regularly and Process pactkets of the primary
45
hw/net/vhost_net.c | 17 +++
35
colo-compare: Update the COLO document to add the IOThread configuration
46
hw/virtio/vhost-iova-tree.c | 2 +-
36
47
hw/virtio/vhost-iova-tree.h | 2 +-
37
Zhang Chen (5):
48
hw/virtio/vhost-shadow-virtqueue.c | 31 +++--
38
net/filter-rewriter.c: Fix rewirter checksum bug when use virtio-net
49
hw/virtio/vhost-vdpa.c | 90 +++++++--------
39
MAINTAINERS: Update mail address for COLO Proxy
50
include/hw/virtio/vhost-vdpa.h | 1 -
40
net/colo-compare.c: Optimize unpredictable tcp options comparison
51
include/net/net.h | 6 +
41
net/colo-compare.c: Adjust net queue pop order for performance
52
include/qemu/iova-tree.h | 2 +-
42
net/colo-compare.c: Fix comments and scheme
53
net/colo.c | 25 ++--
43
54
net/colo.h | 1 +
44
MAINTAINERS | 2 +-
55
net/trace-events | 2 +-
45
docs/colo-proxy.txt | 3 +-
56
net/vhost-vdpa.c | 228 +++++++++++++++++++++++--------------
46
hw/net/e1000.c | 4 +-
57
util/iova-tree.c | 4 +-
47
hw/net/e1000_regs.h | 2 +-
58
15 files changed, 248 insertions(+), 173 deletions(-)
48
hw/net/e1000e_core.c | 2 +-
49
hw/net/e1000x_common.h | 2 +-
50
hw/net/rocker/rocker.c | 94 ++++++----------------
51
hw/net/rocker/rocker_desc.c | 10 ---
52
hw/net/rocker/rocker_fp.c | 4 -
53
hw/net/rocker/rocker_of_dpa.c | 20 -----
54
hw/net/rocker/rocker_world.c | 12 ++-
55
hw/net/rtl8139.c | 53 +-----------
56
include/qemu/sockets.h | 3 +-
57
include/sysemu/iothread.h | 4 +
58
iothread.c | 45 +++++++++++
59
net/colo-compare.c | 183 ++++++++++++++++++++++++------------------
60
net/filter-rewriter.c | 6 +-
61
net/net.c | 22 +++--
62
net/socket.c | 156 +++++++++++++++++++----------------
63
19 files changed, 304 insertions(+), 323 deletions(-)
64
59
65
60
diff view generated by jsdifflib
New patch
1
From: Eugenio Pérez <eperezma@redhat.com>
1
2
3
Next patch will skip the registering of dma maps that the vdpa device
4
rejects in the iova tree. We need to consider that here or we cause a
5
SIGSEGV accessing result.
6
7
Reported-by: Lei Yang <leiyang@redhat.com>
8
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
9
Acked-by: Jason Wang <jasowang@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
---
12
hw/virtio/vhost-vdpa.c | 4 ++++
13
1 file changed, 4 insertions(+)
14
15
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/virtio/vhost-vdpa.c
18
+++ b/hw/virtio/vhost-vdpa.c
19
@@ -XXX,XX +XXX,XX @@ static void vhost_vdpa_listener_region_del(MemoryListener *listener,
20
};
21
22
result = vhost_iova_tree_find_iova(v->iova_tree, &mem_region);
23
+ if (!result) {
24
+ /* The memory listener map wasn't mapped */
25
+ return;
26
+ }
27
iova = result->iova;
28
vhost_iova_tree_remove(v->iova_tree, result);
29
}
30
--
31
2.7.4
32
33
diff view generated by jsdifflib
1
From: Wang Yong <wang.yong155@zte.com.cn>
1
From: Eugenio Pérez <eperezma@redhat.com>
2
2
3
Update colo-proxy.txt,add IOThread configuration.
3
If a map fails for whatever reason, it must not be saved in the tree.
4
Later we have to configure IOThread,if not COLO can not work.
4
Otherwise, qemu will try to unmap it in cleanup, leaving to more errors.
5
5
6
Reviewed-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
6
Fixes: 34e3c94eda ("vdpa: Add custom IOTLB translations to SVQ")
7
Signed-off-by: Wang Yong <wang.yong155@zte.com.cn>
7
Reported-by: Lei Yang <leiyang@redhat.com>
8
Signed-off-by: Wang Guang <wang.guang55@zte.com.cn>
8
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
9
Acked-by: Jason Wang <jasowang@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
11
---
11
docs/colo-proxy.txt | 3 ++-
12
hw/virtio/vhost-vdpa.c | 20 +++++++++++++-------
12
1 file changed, 2 insertions(+), 1 deletion(-)
13
1 file changed, 13 insertions(+), 7 deletions(-)
13
14
14
diff --git a/docs/colo-proxy.txt b/docs/colo-proxy.txt
15
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/docs/colo-proxy.txt
17
--- a/hw/virtio/vhost-vdpa.c
17
+++ b/docs/colo-proxy.txt
18
+++ b/hw/virtio/vhost-vdpa.c
18
@@ -XXX,XX +XXX,XX @@ Primary(ip:3.3.3.3):
19
@@ -XXX,XX +XXX,XX @@ static void vhost_vdpa_listener_commit(MemoryListener *listener)
19
-chardev socket,id=compare0-0,host=3.3.3.3,port=9001
20
static void vhost_vdpa_listener_region_add(MemoryListener *listener,
20
-chardev socket,id=compare_out,host=3.3.3.3,port=9005,server,nowait
21
MemoryRegionSection *section)
21
-chardev socket,id=compare_out0,host=3.3.3.3,port=9005
22
{
22
+-object iothread,id=iothread1
23
+ DMAMap mem_region = {};
23
-object filter-mirror,id=m0,netdev=hn0,queue=tx,outdev=mirror0
24
struct vhost_vdpa *v = container_of(listener, struct vhost_vdpa, listener);
24
-object filter-redirector,netdev=hn0,id=redire0,queue=rx,indev=compare_out
25
hwaddr iova;
25
-object filter-redirector,netdev=hn0,id=redire1,queue=rx,outdev=compare0
26
Int128 llend, llsize;
26
--object colo-compare,id=comp0,primary_in=compare0-0,secondary_in=compare1,outdev=compare_out0
27
@@ -XXX,XX +XXX,XX @@ static void vhost_vdpa_listener_region_add(MemoryListener *listener,
27
+-object colo-compare,id=comp0,primary_in=compare0-0,secondary_in=compare1,outdev=compare_out0,iothread=iothread1
28
28
29
llsize = int128_sub(llend, int128_make64(iova));
29
Secondary(ip:3.3.3.8):
30
if (v->shadow_vqs_enabled) {
30
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,down script=/etc/qemu-ifdown
31
- DMAMap mem_region = {
32
- .translated_addr = (hwaddr)(uintptr_t)vaddr,
33
- .size = int128_get64(llsize) - 1,
34
- .perm = IOMMU_ACCESS_FLAG(true, section->readonly),
35
- };
36
+ int r;
37
38
- int r = vhost_iova_tree_map_alloc(v->iova_tree, &mem_region);
39
+ mem_region.translated_addr = (hwaddr)(uintptr_t)vaddr,
40
+ mem_region.size = int128_get64(llsize) - 1,
41
+ mem_region.perm = IOMMU_ACCESS_FLAG(true, section->readonly),
42
+
43
+ r = vhost_iova_tree_map_alloc(v->iova_tree, &mem_region);
44
if (unlikely(r != IOVA_OK)) {
45
error_report("Can't allocate a mapping (%d)", r);
46
goto fail;
47
@@ -XXX,XX +XXX,XX @@ static void vhost_vdpa_listener_region_add(MemoryListener *listener,
48
vaddr, section->readonly);
49
if (ret) {
50
error_report("vhost vdpa map fail!");
51
- goto fail;
52
+ goto fail_map;
53
}
54
55
return;
56
57
+fail_map:
58
+ if (v->shadow_vqs_enabled) {
59
+ vhost_iova_tree_remove(v->iova_tree, &mem_region);
60
+ }
61
+
62
fail:
63
/*
64
* On the initfn path, store the first error in the container so we
31
--
65
--
32
2.7.4
66
2.7.4
33
67
34
68
diff view generated by jsdifflib
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
1
From: Eugenio Pérez <eperezma@redhat.com>
2
2
3
The rocker device still implements the old PCIDeviceClass .init()
3
It's convenient to call iova_tree_remove from a map returned from
4
instead of the new .realize(). All devices need to be converted to
4
iova_tree_find or iova_tree_find_iova. With the current code this is not
5
.realize().
5
possible, since we will free it, and then we will try to search for it
6
again.
6
7
7
.init() reports errors with fprintf() and return 0 on success, negative
8
Fix it making accepting the map by value, forcing a copy of the
8
number on failure. Meanwhile, when -device rocker fails, it first report
9
argument. Not applying a fixes tag, since there is no use like that at
9
a specific error, then a generic one, like this:
10
the moment.
10
11
11
$ x86_64-softmmu/qemu-system-x86_64 -device rocker,name=qemu-rocker
12
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
12
rocker: name too long; please shorten to at most 9 chars
13
qemu-system-x86_64: -device rocker,name=qemu-rocker: Device initialization failed
14
15
Now, convert it to .realize() that passes errors to its callers via its
16
errp argument. Also avoid the superfluous second error message. After
17
the patch, effect like this:
18
19
$ x86_64-softmmu/qemu-system-x86_64 -device rocker,name=qemu-rocker
20
qemu-system-x86_64: -device rocker,name=qemu-rocker: name too long; please shorten to at most 9 chars
21
22
Cc: jasowang@redhat.com
23
Cc: jiri@resnulli.us
24
Cc: armbru@redhat.com
25
Cc: f4bug@amsat.org
26
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
27
Reviewed-by: Markus Armbruster <armbru@redhat.com>
28
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
29
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
Signed-off-by: Jason Wang <jasowang@redhat.com>
30
---
14
---
31
hw/net/rocker/rocker.c | 27 +++++++++++----------------
15
hw/i386/intel_iommu.c | 6 +++---
32
1 file changed, 11 insertions(+), 16 deletions(-)
16
hw/virtio/vhost-iova-tree.c | 2 +-
17
hw/virtio/vhost-iova-tree.h | 2 +-
18
hw/virtio/vhost-vdpa.c | 6 +++---
19
include/qemu/iova-tree.h | 2 +-
20
net/vhost-vdpa.c | 4 ++--
21
util/iova-tree.c | 4 ++--
22
7 files changed, 13 insertions(+), 13 deletions(-)
33
23
34
diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c
24
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
35
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/net/rocker/rocker.c
26
--- a/hw/i386/intel_iommu.c
37
+++ b/hw/net/rocker/rocker.c
27
+++ b/hw/i386/intel_iommu.c
38
@@ -XXX,XX +XXX,XX @@ rollback:
28
@@ -XXX,XX +XXX,XX @@ static int vtd_page_walk_one(IOMMUTLBEvent *event, vtd_page_walk_info *info)
39
return err;
29
return ret;
30
}
31
/* Drop any existing mapping */
32
- iova_tree_remove(as->iova_tree, &target);
33
+ iova_tree_remove(as->iova_tree, target);
34
/* Recover the correct type */
35
event->type = IOMMU_NOTIFIER_MAP;
36
entry->perm = cache_perm;
37
@@ -XXX,XX +XXX,XX @@ static int vtd_page_walk_one(IOMMUTLBEvent *event, vtd_page_walk_info *info)
38
trace_vtd_page_walk_one_skip_unmap(entry->iova, entry->addr_mask);
39
return 0;
40
}
41
- iova_tree_remove(as->iova_tree, &target);
42
+ iova_tree_remove(as->iova_tree, target);
43
}
44
45
trace_vtd_page_walk_one(info->domain_id, entry->iova,
46
@@ -XXX,XX +XXX,XX @@ static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n)
47
48
map.iova = n->start;
49
map.size = size;
50
- iova_tree_remove(as->iova_tree, &map);
51
+ iova_tree_remove(as->iova_tree, map);
40
}
52
}
41
53
42
-static int rocker_msix_init(Rocker *r)
54
static void vtd_address_space_unmap_all(IntelIOMMUState *s)
43
+static int rocker_msix_init(Rocker *r, Error **errp)
55
diff --git a/hw/virtio/vhost-iova-tree.c b/hw/virtio/vhost-iova-tree.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/hw/virtio/vhost-iova-tree.c
58
+++ b/hw/virtio/vhost-iova-tree.c
59
@@ -XXX,XX +XXX,XX @@ int vhost_iova_tree_map_alloc(VhostIOVATree *tree, DMAMap *map)
60
* @iova_tree: The vhost iova tree
61
* @map: The map to remove
62
*/
63
-void vhost_iova_tree_remove(VhostIOVATree *iova_tree, const DMAMap *map)
64
+void vhost_iova_tree_remove(VhostIOVATree *iova_tree, DMAMap map)
44
{
65
{
45
PCIDevice *dev = PCI_DEVICE(r);
66
iova_tree_remove(iova_tree->iova_taddr_map, map);
46
int err;
67
}
47
- Error *local_err = NULL;
68
diff --git a/hw/virtio/vhost-iova-tree.h b/hw/virtio/vhost-iova-tree.h
48
69
index XXXXXXX..XXXXXXX 100644
49
err = msix_init(dev, ROCKER_MSIX_VEC_COUNT(r->fp_ports),
70
--- a/hw/virtio/vhost-iova-tree.h
50
&r->msix_bar,
71
+++ b/hw/virtio/vhost-iova-tree.h
51
ROCKER_PCI_MSIX_BAR_IDX, ROCKER_PCI_MSIX_TABLE_OFFSET,
72
@@ -XXX,XX +XXX,XX @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(VhostIOVATree, vhost_iova_tree_delete);
52
&r->msix_bar,
73
const DMAMap *vhost_iova_tree_find_iova(const VhostIOVATree *iova_tree,
53
ROCKER_PCI_MSIX_BAR_IDX, ROCKER_PCI_MSIX_PBA_OFFSET,
74
const DMAMap *map);
54
- 0, &local_err);
75
int vhost_iova_tree_map_alloc(VhostIOVATree *iova_tree, DMAMap *map);
55
+ 0, errp);
76
-void vhost_iova_tree_remove(VhostIOVATree *iova_tree, const DMAMap *map);
56
if (err) {
77
+void vhost_iova_tree_remove(VhostIOVATree *iova_tree, DMAMap map);
57
- error_report_err(local_err);
78
58
return err;
79
#endif
80
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/hw/virtio/vhost-vdpa.c
83
+++ b/hw/virtio/vhost-vdpa.c
84
@@ -XXX,XX +XXX,XX @@ static void vhost_vdpa_listener_region_add(MemoryListener *listener,
85
86
fail_map:
87
if (v->shadow_vqs_enabled) {
88
- vhost_iova_tree_remove(v->iova_tree, &mem_region);
89
+ vhost_iova_tree_remove(v->iova_tree, mem_region);
59
}
90
}
60
91
61
@@ -XXX,XX +XXX,XX @@ static World *rocker_world_type_by_name(Rocker *r, const char *name)
92
fail:
62
return NULL;
93
@@ -XXX,XX +XXX,XX @@ static void vhost_vdpa_listener_region_del(MemoryListener *listener,
94
return;
95
}
96
iova = result->iova;
97
- vhost_iova_tree_remove(v->iova_tree, result);
98
+ vhost_iova_tree_remove(v->iova_tree, *result);
99
}
100
vhost_vdpa_iotlb_batch_begin_once(v);
101
ret = vhost_vdpa_dma_unmap(v, iova, int128_get64(llsize));
102
@@ -XXX,XX +XXX,XX @@ static bool vhost_vdpa_svq_map_ring(struct vhost_vdpa *v, DMAMap *needle,
103
needle->perm == IOMMU_RO);
104
if (unlikely(r != 0)) {
105
error_setg_errno(errp, -r, "Cannot map region to device");
106
- vhost_iova_tree_remove(v->iova_tree, needle);
107
+ vhost_iova_tree_remove(v->iova_tree, *needle);
108
}
109
110
return r == 0;
111
diff --git a/include/qemu/iova-tree.h b/include/qemu/iova-tree.h
112
index XXXXXXX..XXXXXXX 100644
113
--- a/include/qemu/iova-tree.h
114
+++ b/include/qemu/iova-tree.h
115
@@ -XXX,XX +XXX,XX @@ int iova_tree_insert(IOVATree *tree, const DMAMap *map);
116
* all the mappings that are included in the provided range will be
117
* removed from the tree. Here map->translated_addr is meaningless.
118
*/
119
-void iova_tree_remove(IOVATree *tree, const DMAMap *map);
120
+void iova_tree_remove(IOVATree *tree, DMAMap map);
121
122
/**
123
* iova_tree_find:
124
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
125
index XXXXXXX..XXXXXXX 100644
126
--- a/net/vhost-vdpa.c
127
+++ b/net/vhost-vdpa.c
128
@@ -XXX,XX +XXX,XX @@ static void vhost_vdpa_cvq_unmap_buf(struct vhost_vdpa *v, void *addr)
129
error_report("Device cannot unmap: %s(%d)", g_strerror(r), r);
130
}
131
132
- vhost_iova_tree_remove(tree, map);
133
+ vhost_iova_tree_remove(tree, *map);
63
}
134
}
64
135
65
-static int pci_rocker_init(PCIDevice *dev)
136
static size_t vhost_vdpa_net_cvq_cmd_len(void)
66
+static void pci_rocker_realize(PCIDevice *dev, Error **errp)
137
@@ -XXX,XX +XXX,XX @@ static bool vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v,
138
return true;
139
140
dma_map_err:
141
- vhost_iova_tree_remove(v->iova_tree, &map);
142
+ vhost_iova_tree_remove(v->iova_tree, map);
143
return false;
144
}
145
146
diff --git a/util/iova-tree.c b/util/iova-tree.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/util/iova-tree.c
149
+++ b/util/iova-tree.c
150
@@ -XXX,XX +XXX,XX @@ void iova_tree_foreach(IOVATree *tree, iova_tree_iterator iterator)
151
g_tree_foreach(tree->tree, iova_tree_traverse, iterator);
152
}
153
154
-void iova_tree_remove(IOVATree *tree, const DMAMap *map)
155
+void iova_tree_remove(IOVATree *tree, DMAMap map)
67
{
156
{
68
Rocker *r = to_rocker(dev);
157
const DMAMap *overlap;
69
const MACAddr zero = { .a = { 0, 0, 0, 0, 0, 0 } };
158
70
@@ -XXX,XX +XXX,XX @@ static int pci_rocker_init(PCIDevice *dev)
159
- while ((overlap = iova_tree_find(tree, map))) {
71
160
+ while ((overlap = iova_tree_find(tree, &map))) {
72
r->world_dflt = rocker_world_type_by_name(r, r->world_name);
161
g_tree_remove(tree->tree, overlap);
73
if (!r->world_dflt) {
74
- fprintf(stderr,
75
- "rocker: requested world \"%s\" does not exist\n",
76
+ error_setg(errp,
77
+ "invalid argument requested world %s does not exist",
78
r->world_name);
79
- err = -EINVAL;
80
goto err_world_type_by_name;
81
}
162
}
82
83
@@ -XXX,XX +XXX,XX @@ static int pci_rocker_init(PCIDevice *dev)
84
85
/* MSI-X init */
86
87
- err = rocker_msix_init(r);
88
+ err = rocker_msix_init(r, errp);
89
if (err) {
90
goto err_msix_init;
91
}
92
@@ -XXX,XX +XXX,XX @@ static int pci_rocker_init(PCIDevice *dev)
93
}
94
95
if (rocker_find(r->name)) {
96
- err = -EEXIST;
97
+ error_setg(errp, "%s already exists", r->name);
98
goto err_duplicate;
99
}
100
101
@@ -XXX,XX +XXX,XX @@ static int pci_rocker_init(PCIDevice *dev)
102
#define ROCKER_IFNAMSIZ 16
103
#define MAX_ROCKER_NAME_LEN (ROCKER_IFNAMSIZ - 1 - 3 - 3)
104
if (strlen(r->name) > MAX_ROCKER_NAME_LEN) {
105
- fprintf(stderr,
106
- "rocker: name too long; please shorten to at most %d chars\n",
107
+ error_setg(errp,
108
+ "name too long; please shorten to at most %d chars",
109
MAX_ROCKER_NAME_LEN);
110
- err = -EINVAL;
111
goto err_name_too_long;
112
}
113
114
@@ -XXX,XX +XXX,XX @@ static int pci_rocker_init(PCIDevice *dev)
115
116
QLIST_INSERT_HEAD(&rockers, r, next);
117
118
- return 0;
119
+ return;
120
121
err_name_too_long:
122
err_duplicate:
123
@@ -XXX,XX +XXX,XX @@ err_world_type_by_name:
124
world_free(r->worlds[i]);
125
}
126
}
127
- return err;
128
}
163
}
129
130
static void pci_rocker_uninit(PCIDevice *dev)
131
@@ -XXX,XX +XXX,XX @@ static void rocker_class_init(ObjectClass *klass, void *data)
132
DeviceClass *dc = DEVICE_CLASS(klass);
133
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
134
135
- k->init = pci_rocker_init;
136
+ k->realize = pci_rocker_realize;
137
k->exit = pci_rocker_uninit;
138
k->vendor_id = PCI_VENDOR_ID_REDHAT;
139
k->device_id = PCI_DEVICE_ID_REDHAT_ROCKER;
140
--
164
--
141
2.7.4
165
2.7.4
142
166
143
167
diff view generated by jsdifflib
1
From: Wang Yong <wang.yong155@zte.com.cn>
1
From: Eugenio Pérez <eperezma@redhat.com>
2
2
3
Remove the task which check old packet in the comparing thread,
3
Although the device will be reset before usage, the right thing to do is
4
then use IOthread context timer to handle it.
4
to clean it.
5
5
6
Process pactkets in the IOThread which arrived over the socket.
6
Reported-by: Lei Yang <leiyang@redhat.com>
7
we use iothread_get_g_main_context to create a new g_main_loop in
7
Fixes: 34e3c94eda ("vdpa: Add custom IOTLB translations to SVQ")
8
the IOThread.then the packets from the primary and the secondary
8
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
9
are processed in the IOThread.
10
11
Finally remove the colo-compare thread using the IOThread instead.
12
13
Reviewed-by: Zhang Chen<zhangchen.fnst@cn.fujitsu.com>
14
Signed-off-by: Wang Yong <wang.yong155@zte.com.cn>
15
Signed-off-by: Wang Guang <wang.guang55@zte.com.cn>
16
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
17
---
10
---
18
net/colo-compare.c | 83 +++++++++++++++++++++++++++++-------------------------
11
hw/virtio/vhost-vdpa.c | 6 ++++++
19
1 file changed, 45 insertions(+), 38 deletions(-)
12
1 file changed, 6 insertions(+)
20
13
21
diff --git a/net/colo-compare.c b/net/colo-compare.c
14
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
22
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
23
--- a/net/colo-compare.c
16
--- a/hw/virtio/vhost-vdpa.c
24
+++ b/net/colo-compare.c
17
+++ b/hw/virtio/vhost-vdpa.c
25
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static bool vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v,
26
#include "qemu/sockets.h"
19
27
#include "qapi-visit.h"
20
size = ROUND_UP(result->size, qemu_real_host_page_size());
28
#include "net/colo.h"
21
r = vhost_vdpa_dma_unmap(v, result->iova, size);
29
+#include "sysemu/iothread.h"
22
+ if (unlikely(r < 0)) {
30
23
+ error_report("Unable to unmap SVQ vring: %s (%d)", g_strerror(-r), -r);
31
#define TYPE_COLO_COMPARE "colo-compare"
24
+ return false;
32
#define COLO_COMPARE(obj) \
33
@@ -XXX,XX +XXX,XX @@ typedef struct CompareState {
34
GQueue conn_list;
35
/* Record the connection without repetition */
36
GHashTable *connection_track_table;
37
- /* This thread just do packet compare job */
38
- QemuThread thread;
39
40
+ IOThread *iothread;
41
GMainContext *worker_context;
42
- GMainLoop *compare_loop;
43
+ QEMUTimer *packet_check_timer;
44
} CompareState;
45
46
typedef struct CompareClass {
47
@@ -XXX,XX +XXX,XX @@ static void compare_sec_chr_in(void *opaque, const uint8_t *buf, int size)
48
* Check old packet regularly so it can watch for any packets
49
* that the secondary hasn't produced equivalents of.
50
*/
51
-static gboolean check_old_packet_regular(void *opaque)
52
+static void check_old_packet_regular(void *opaque)
53
{
54
CompareState *s = opaque;
55
56
/* if have old packet we will notify checkpoint */
57
colo_old_packet_check(s);
58
+ timer_mod(s->packet_check_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
59
+ REGULAR_PACKET_CHECK_MS);
60
+}
61
+
62
+static void colo_compare_timer_init(CompareState *s)
63
+{
64
+ AioContext *ctx = iothread_get_aio_context(s->iothread);
65
66
- return TRUE;
67
+ s->packet_check_timer = aio_timer_new(ctx, QEMU_CLOCK_VIRTUAL,
68
+ SCALE_MS, check_old_packet_regular,
69
+ s);
70
+ timer_mod(s->packet_check_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
71
+ REGULAR_PACKET_CHECK_MS);
72
}
73
74
-static void *colo_compare_thread(void *opaque)
75
+static void colo_compare_timer_del(CompareState *s)
76
{
77
- CompareState *s = opaque;
78
- GSource *timeout_source;
79
+ if (s->packet_check_timer) {
80
+ timer_del(s->packet_check_timer);
81
+ timer_free(s->packet_check_timer);
82
+ s->packet_check_timer = NULL;
83
+ }
84
+ }
85
86
- s->worker_context = g_main_context_new();
87
+static void colo_compare_iothread(CompareState *s)
88
+{
89
+ object_ref(OBJECT(s->iothread));
90
+ s->worker_context = iothread_get_g_main_context(s->iothread);
91
92
qemu_chr_fe_set_handlers(&s->chr_pri_in, compare_chr_can_read,
93
compare_pri_chr_in, NULL, NULL,
94
@@ -XXX,XX +XXX,XX @@ static void *colo_compare_thread(void *opaque)
95
compare_sec_chr_in, NULL, NULL,
96
s, s->worker_context, true);
97
98
- s->compare_loop = g_main_loop_new(s->worker_context, FALSE);
99
-
100
- /* To kick any packets that the secondary doesn't match */
101
- timeout_source = g_timeout_source_new(REGULAR_PACKET_CHECK_MS);
102
- g_source_set_callback(timeout_source,
103
- (GSourceFunc)check_old_packet_regular, s, NULL);
104
- g_source_attach(timeout_source, s->worker_context);
105
-
106
- g_main_loop_run(s->compare_loop);
107
-
108
- g_source_unref(timeout_source);
109
- g_main_loop_unref(s->compare_loop);
110
- g_main_context_unref(s->worker_context);
111
- return NULL;
112
+ colo_compare_timer_init(s);
113
}
114
115
static char *compare_get_pri_indev(Object *obj, Error **errp)
116
@@ -XXX,XX +XXX,XX @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
117
{
118
CompareState *s = COLO_COMPARE(uc);
119
Chardev *chr;
120
- char thread_name[64];
121
- static int compare_id;
122
123
- if (!s->pri_indev || !s->sec_indev || !s->outdev) {
124
+ if (!s->pri_indev || !s->sec_indev || !s->outdev || !s->iothread) {
125
error_setg(errp, "colo compare needs 'primary_in' ,"
126
- "'secondary_in','outdev' property set");
127
+ "'secondary_in','outdev','iothread' property set");
128
return;
129
} else if (!strcmp(s->pri_indev, s->outdev) ||
130
!strcmp(s->sec_indev, s->outdev) ||
131
@@ -XXX,XX +XXX,XX @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
132
g_free,
133
connection_destroy);
134
135
- sprintf(thread_name, "colo-compare %d", compare_id);
136
- qemu_thread_create(&s->thread, thread_name,
137
- colo_compare_thread, s,
138
- QEMU_THREAD_JOINABLE);
139
- compare_id++;
140
-
141
+ colo_compare_iothread(s);
142
return;
143
}
144
145
@@ -XXX,XX +XXX,XX @@ static void colo_compare_init(Object *obj)
146
object_property_add_str(obj, "outdev",
147
compare_get_outdev, compare_set_outdev,
148
NULL);
149
+ object_property_add_link(obj, "iothread", TYPE_IOTHREAD,
150
+ (Object **)&s->iothread,
151
+ object_property_allow_set_link,
152
+ OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL);
153
154
s->vnet_hdr = false;
155
object_property_add_bool(obj, "vnet_hdr_support", compare_get_vnet_hdr,
156
@@ -XXX,XX +XXX,XX @@ static void colo_compare_finalize(Object *obj)
157
qemu_chr_fe_deinit(&s->chr_pri_in, false);
158
qemu_chr_fe_deinit(&s->chr_sec_in, false);
159
qemu_chr_fe_deinit(&s->chr_out, false);
160
-
161
- g_main_loop_quit(s->compare_loop);
162
- qemu_thread_join(&s->thread);
163
-
164
+ if (s->iothread) {
165
+ colo_compare_timer_del(s);
166
+ }
167
/* Release all unhandled packets after compare thead exited */
168
g_queue_foreach(&s->conn_list, colo_flush_packets, s);
169
170
g_queue_clear(&s->conn_list);
171
172
- g_hash_table_destroy(s->connection_track_table);
173
+ if (s->connection_track_table) {
174
+ g_hash_table_destroy(s->connection_track_table);
175
+ }
25
+ }
176
+
26
+
177
+ if (s->iothread) {
27
+ vhost_iova_tree_remove(v->iova_tree, *result);
178
+ object_unref(OBJECT(s->iothread));
28
return r == 0;
179
+ }
29
}
180
g_free(s->pri_indev);
30
181
g_free(s->sec_indev);
182
g_free(s->outdev);
183
--
31
--
184
2.7.4
32
2.7.4
185
33
186
34
diff view generated by jsdifflib
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
1
From: Eugenio Pérez <eperezma@redhat.com>
2
2
3
Memory allocation functions like world_alloc, desc_ring_alloc etc,
3
Nothing actually reads the return value, but an error in cleaning some
4
they are all wrappers around g_malloc, g_new etc. But g_malloc and
4
entries could cause device stop to abort, making a restart impossible.
5
similar functions doesn't return null. Because they ignore the fact
5
Better ignore explicitely the return value.
6
that g_malloc() of 0 bytes returns null. So error checks for these
7
allocation failure are superfluous. Now, remove them entirely.
8
6
9
Cc: jasowang@redhat.com
7
Reported-by: Lei Yang <leiyang@redhat.com>
10
Cc: jiri@resnulli.us
8
Fixes: 34e3c94eda ("vdpa: Add custom IOTLB translations to SVQ")
11
Cc: armbru@redhat.com
9
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
12
Cc: f4bug@amsat.org
10
Acked-by: Jason Wang <jasowang@redhat.com>
13
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
14
Reviewed-by: Markus Armbruster <armbru@redhat.com>
15
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
16
---
12
---
17
hw/net/rocker/rocker.c | 47 +------------------------------------------
13
hw/virtio/vhost-vdpa.c | 32 ++++++++++----------------------
18
hw/net/rocker/rocker_desc.c | 10 ---------
14
1 file changed, 10 insertions(+), 22 deletions(-)
19
hw/net/rocker/rocker_fp.c | 4 ----
20
hw/net/rocker/rocker_of_dpa.c | 20 ------------------
21
hw/net/rocker/rocker_world.c | 12 +++++------
22
5 files changed, 6 insertions(+), 87 deletions(-)
23
15
24
diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c
16
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
25
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/net/rocker/rocker.c
18
--- a/hw/virtio/vhost-vdpa.c
27
+++ b/hw/net/rocker/rocker.c
19
+++ b/hw/virtio/vhost-vdpa.c
28
@@ -XXX,XX +XXX,XX @@ static int tx_consume(Rocker *r, DescInfo *info)
20
@@ -XXX,XX +XXX,XX @@ static int vhost_vdpa_svq_set_fds(struct vhost_dev *dev,
29
}
21
/**
30
iov[iovcnt].iov_len = frag_len;
22
* Unmap a SVQ area in the device
31
iov[iovcnt].iov_base = g_malloc(frag_len);
23
*/
32
- if (!iov[iovcnt].iov_base) {
24
-static bool vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v,
33
- err = -ROCKER_ENOMEM;
25
+static void vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v,
34
- goto err_no_mem;
26
const DMAMap *needle)
35
- }
27
{
36
28
const DMAMap *result = vhost_iova_tree_find_iova(v->iova_tree, needle);
37
pci_dma_read(dev, frag_addr, iov[iovcnt].iov_base,
29
@@ -XXX,XX +XXX,XX @@ static bool vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v,
38
iov[iovcnt].iov_len);
30
39
@@ -XXX,XX +XXX,XX @@ static int tx_consume(Rocker *r, DescInfo *info)
31
if (unlikely(!result)) {
40
err = fp_port_eg(r->fp_port[port], iov, iovcnt);
32
error_report("Unable to find SVQ address to unmap");
41
33
- return false;
42
err_too_many_frags:
34
+ return;
43
-err_no_mem:
44
err_bad_attr:
45
for (i = 0; i < ROCKER_TX_FRAGS_MAX; i++) {
46
g_free(iov[i].iov_base);
47
@@ -XXX,XX +XXX,XX @@ int rx_produce(World *world, uint32_t pport,
48
*/
49
50
data = g_malloc(data_size);
51
- if (!data) {
52
- err = -ROCKER_ENOMEM;
53
- goto out;
54
- }
55
+
56
iov_to_buf(iov, iovcnt, 0, data, data_size);
57
pci_dma_write(dev, frag_addr, data, data_size);
58
g_free(data);
59
@@ -XXX,XX +XXX,XX @@ static void rocker_test_dma_ctrl(Rocker *r, uint32_t val)
60
61
buf = g_malloc(r->test_dma_size);
62
63
- if (!buf) {
64
- DPRINTF("test dma buffer alloc failed");
65
- return;
66
- }
67
-
68
switch (val) {
69
case ROCKER_TEST_DMA_CTRL_CLEAR:
70
memset(buf, 0, r->test_dma_size);
71
@@ -XXX,XX +XXX,XX @@ static int pci_rocker_init(PCIDevice *dev)
72
73
r->worlds[ROCKER_WORLD_TYPE_OF_DPA] = of_dpa_world_alloc(r);
74
75
- for (i = 0; i < ROCKER_WORLD_TYPE_MAX; i++) {
76
- if (!r->worlds[i]) {
77
- err = -ENOMEM;
78
- goto err_world_alloc;
79
- }
80
- }
81
-
82
if (!r->world_name) {
83
r->world_name = g_strdup(world_name(r->worlds[ROCKER_WORLD_TYPE_OF_DPA]));
84
}
35
}
85
@@ -XXX,XX +XXX,XX @@ static int pci_rocker_init(PCIDevice *dev)
36
37
size = ROUND_UP(result->size, qemu_real_host_page_size());
38
r = vhost_vdpa_dma_unmap(v, result->iova, size);
39
if (unlikely(r < 0)) {
40
error_report("Unable to unmap SVQ vring: %s (%d)", g_strerror(-r), -r);
41
- return false;
42
+ return;
86
}
43
}
87
44
88
r->rings = g_new(DescRing *, rocker_pci_ring_count(r));
45
vhost_iova_tree_remove(v->iova_tree, *result);
89
- if (!r->rings) {
46
- return r == 0;
90
- goto err_rings_alloc;
47
}
91
- }
48
92
49
-static bool vhost_vdpa_svq_unmap_rings(struct vhost_dev *dev,
93
/* Rings are ordered like this:
50
+static void vhost_vdpa_svq_unmap_rings(struct vhost_dev *dev,
94
* - command ring
51
const VhostShadowVirtqueue *svq)
95
@@ -XXX,XX +XXX,XX @@ static int pci_rocker_init(PCIDevice *dev)
52
{
96
* .....
53
DMAMap needle = {};
97
*/
54
struct vhost_vdpa *v = dev->opaque;
98
55
struct vhost_vring_addr svq_addr;
99
- err = -ENOMEM;
56
- bool ok;
100
for (i = 0; i < rocker_pci_ring_count(r); i++) {
57
101
DescRing *ring = desc_ring_alloc(r, i);
58
vhost_svq_get_vring_addr(svq, &svq_addr);
102
59
103
- if (!ring) {
60
needle.translated_addr = svq_addr.desc_user_addr;
104
- goto err_ring_alloc;
61
- ok = vhost_vdpa_svq_unmap_ring(v, &needle);
105
- }
62
- if (unlikely(!ok)) {
106
-
107
if (i == ROCKER_RING_CMD) {
108
desc_ring_set_consume(ring, cmd_consume, ROCKER_MSIX_VEC_CMD);
109
} else if (i == ROCKER_RING_EVENT) {
110
@@ -XXX,XX +XXX,XX @@ static int pci_rocker_init(PCIDevice *dev)
111
fp_port_alloc(r, r->name, &r->fp_start_macaddr,
112
i, &r->fp_ports_peers[i]);
113
114
- if (!port) {
115
- goto err_port_alloc;
116
- }
117
-
118
r->fp_port[i] = port;
119
fp_port_set_world(port, r->world_dflt);
120
}
121
@@ -XXX,XX +XXX,XX @@ static int pci_rocker_init(PCIDevice *dev)
122
123
return 0;
124
125
-err_port_alloc:
126
- for (--i; i >= 0; i--) {
127
- FpPort *port = r->fp_port[i];
128
- fp_port_free(port);
129
- }
130
- i = rocker_pci_ring_count(r);
131
-err_ring_alloc:
132
- for (--i; i >= 0; i--) {
133
- desc_ring_free(r->rings[i]);
134
- }
135
- g_free(r->rings);
136
-err_rings_alloc:
137
err_duplicate:
138
rocker_msix_uninit(r);
139
err_msix_init:
140
object_unparent(OBJECT(&r->msix_bar));
141
object_unparent(OBJECT(&r->mmio));
142
err_world_type_by_name:
143
-err_world_alloc:
144
for (i = 0; i < ROCKER_WORLD_TYPE_MAX; i++) {
145
if (r->worlds[i]) {
146
world_free(r->worlds[i]);
147
diff --git a/hw/net/rocker/rocker_desc.c b/hw/net/rocker/rocker_desc.c
148
index XXXXXXX..XXXXXXX 100644
149
--- a/hw/net/rocker/rocker_desc.c
150
+++ b/hw/net/rocker/rocker_desc.c
151
@@ -XXX,XX +XXX,XX @@ char *desc_get_buf(DescInfo *info, bool read_only)
152
info->buf_size = size;
153
}
154
155
- if (!info->buf) {
156
- return NULL;
157
- }
158
-
159
pci_dma_read(dev, le64_to_cpu(info->desc.buf_addr), info->buf, size);
160
161
return info->buf;
162
@@ -XXX,XX +XXX,XX @@ bool desc_ring_set_size(DescRing *ring, uint32_t size)
163
ring->head = ring->tail = 0;
164
165
ring->info = g_renew(DescInfo, ring->info, size);
166
- if (!ring->info) {
167
- return false;
63
- return false;
168
- }
64
- }
169
65
+ vhost_vdpa_svq_unmap_ring(v, &needle);
170
memset(ring->info, 0, size * sizeof(DescInfo));
66
171
67
needle.translated_addr = svq_addr.used_user_addr;
172
@@ -XXX,XX +XXX,XX @@ DescRing *desc_ring_alloc(Rocker *r, int index)
68
- return vhost_vdpa_svq_unmap_ring(v, &needle);
173
DescRing *ring;
69
+ vhost_vdpa_svq_unmap_ring(v, &needle);
174
70
}
175
ring = g_new0(DescRing, 1);
71
176
- if (!ring) {
72
/**
177
- return NULL;
73
@@ -XXX,XX +XXX,XX @@ err:
178
- }
74
return false;
179
75
}
180
ring->r = r;
76
181
ring->index = index;
77
-static bool vhost_vdpa_svqs_stop(struct vhost_dev *dev)
182
diff --git a/hw/net/rocker/rocker_fp.c b/hw/net/rocker/rocker_fp.c
78
+static void vhost_vdpa_svqs_stop(struct vhost_dev *dev)
183
index XXXXXXX..XXXXXXX 100644
184
--- a/hw/net/rocker/rocker_fp.c
185
+++ b/hw/net/rocker/rocker_fp.c
186
@@ -XXX,XX +XXX,XX @@ FpPort *fp_port_alloc(Rocker *r, char *sw_name,
187
{
79
{
188
FpPort *port = g_new0(FpPort, 1);
80
struct vhost_vdpa *v = dev->opaque;
189
81
190
- if (!port) {
82
if (!v->shadow_vqs) {
191
- return NULL;
83
- return true;
192
- }
84
+ return;
193
-
194
port->r = r;
195
port->index = index;
196
port->pport = index + 1;
197
diff --git a/hw/net/rocker/rocker_of_dpa.c b/hw/net/rocker/rocker_of_dpa.c
198
index XXXXXXX..XXXXXXX 100644
199
--- a/hw/net/rocker/rocker_of_dpa.c
200
+++ b/hw/net/rocker/rocker_of_dpa.c
201
@@ -XXX,XX +XXX,XX @@ static OfDpaFlow *of_dpa_flow_alloc(uint64_t cookie)
202
int64_t now = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) / 1000;
203
204
flow = g_new0(OfDpaFlow, 1);
205
- if (!flow) {
206
- return NULL;
207
- }
208
209
flow->cookie = cookie;
210
flow->mask.tbl_id = 0xffffffff;
211
@@ -XXX,XX +XXX,XX @@ static OfDpaGroup *of_dpa_group_alloc(uint32_t id)
212
{
213
OfDpaGroup *group = g_new0(OfDpaGroup, 1);
214
215
- if (!group) {
216
- return NULL;
217
- }
218
-
219
group->id = id;
220
221
return group;
222
@@ -XXX,XX +XXX,XX @@ static int of_dpa_cmd_flow_add(OfDpa *of_dpa, uint64_t cookie,
223
}
85
}
224
86
225
flow = of_dpa_flow_alloc(cookie);
87
for (unsigned i = 0; i < v->shadow_vqs->len; ++i) {
226
- if (!flow) {
88
VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i);
227
- return -ROCKER_ENOMEM;
89
- bool ok = vhost_vdpa_svq_unmap_rings(dev, svq);
228
- }
90
- if (unlikely(!ok)) {
229
91
- return false;
230
err = of_dpa_cmd_flow_add_mod(of_dpa, flow, flow_tlvs);
92
- }
231
if (err) {
93
+ vhost_vdpa_svq_unmap_rings(dev, svq);
232
@@ -XXX,XX +XXX,XX @@ static int of_dpa_cmd_add_l2_flood(OfDpa *of_dpa, OfDpaGroup *group,
233
rocker_tlv_get_le16(group_tlvs[ROCKER_TLV_OF_DPA_GROUP_COUNT]);
234
235
tlvs = g_new0(RockerTlv *, group->l2_flood.group_count + 1);
236
- if (!tlvs) {
237
- return -ROCKER_ENOMEM;
238
- }
239
240
g_free(group->l2_flood.group_ids);
241
group->l2_flood.group_ids =
242
g_new0(uint32_t, group->l2_flood.group_count);
243
- if (!group->l2_flood.group_ids) {
244
- err = -ROCKER_ENOMEM;
245
- goto err_out;
246
- }
247
248
rocker_tlv_parse_nested(tlvs, group->l2_flood.group_count,
249
group_tlvs[ROCKER_TLV_OF_DPA_GROUP_IDS]);
250
@@ -XXX,XX +XXX,XX @@ static int of_dpa_cmd_group_add(OfDpa *of_dpa, uint32_t group_id,
251
}
94
}
252
95
253
group = of_dpa_group_alloc(group_id);
96
if (v->migration_blocker) {
254
- if (!group) {
97
migrate_del_blocker(v->migration_blocker);
255
- return -ROCKER_ENOMEM;
98
}
256
- }
99
- return true;
257
100
}
258
err = of_dpa_cmd_group_do(of_dpa, group_id, group, group_tlvs);
101
259
if (err) {
102
static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started)
260
diff --git a/hw/net/rocker/rocker_world.c b/hw/net/rocker/rocker_world.c
103
@@ -XXX,XX +XXX,XX @@ static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started)
261
index XXXXXXX..XXXXXXX 100644
104
}
262
--- a/hw/net/rocker/rocker_world.c
105
vhost_vdpa_set_vring_ready(dev);
263
+++ b/hw/net/rocker/rocker_world.c
106
} else {
264
@@ -XXX,XX +XXX,XX @@ World *world_alloc(Rocker *r, size_t sizeof_private,
107
- ok = vhost_vdpa_svqs_stop(dev);
265
{
108
- if (unlikely(!ok)) {
266
World *w = g_malloc0(sizeof(World) + sizeof_private);
109
- return -1;
267
268
- if (w) {
269
- w->r = r;
270
- w->type = type;
271
- w->ops = ops;
272
- if (w->ops->init) {
273
- w->ops->init(w);
274
- }
110
- }
275
+ w->r = r;
111
+ vhost_vdpa_svqs_stop(dev);
276
+ w->type = type;
112
vhost_vdpa_host_notifiers_uninit(dev, dev->nvqs);
277
+ w->ops = ops;
278
+ if (w->ops->init) {
279
+ w->ops->init(w);
280
}
113
}
281
114
282
return w;
283
--
115
--
284
2.7.4
116
2.7.4
285
117
286
118
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Eugenio Pérez <eperezma@redhat.com>
2
2
3
The packet_enqueue() use g_queue_push_tail() to
3
We can unbind twice a file descriptor if we call twice
4
enqueue net packet, so it is more efficent way use
4
vhost_svq_set_svq_kick_fd because of this. Since it comes from vhost and
5
g_queue_pop_head() to get packet for compare.
5
not from SVQ, that file descriptor could be a different thing that
6
That will improve the success rate of comparison.
6
guest's vhost notifier.
7
In my test the performance of ftp put 1000M file
8
will increase 10%
9
7
10
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
8
Likewise, it can happens the same if a guest start and stop the device
9
multiple times.
10
11
Reported-by: Lei Yang <leiyang@redhat.com>
12
Fixes: dff4426fa6 ("vhost: Add Shadow VirtQueue kick forwarding capabilities")
13
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
14
Acked-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
15
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
16
---
13
net/colo-compare.c | 4 ++--
17
hw/virtio/vhost-shadow-virtqueue.c | 4 ++--
14
1 file changed, 2 insertions(+), 2 deletions(-)
18
1 file changed, 2 insertions(+), 2 deletions(-)
15
19
16
diff --git a/net/colo-compare.c b/net/colo-compare.c
20
diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
17
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
18
--- a/net/colo-compare.c
22
--- a/hw/virtio/vhost-shadow-virtqueue.c
19
+++ b/net/colo-compare.c
23
+++ b/hw/virtio/vhost-shadow-virtqueue.c
20
@@ -XXX,XX +XXX,XX @@ static void colo_compare_connection(void *opaque, void *user_data)
24
@@ -XXX,XX +XXX,XX @@ void vhost_svq_set_svq_kick_fd(VhostShadowVirtqueue *svq, int svq_kick_fd)
21
25
event_notifier_set_handler(svq_kick, NULL);
22
while (!g_queue_is_empty(&conn->primary_list) &&
26
}
23
!g_queue_is_empty(&conn->secondary_list)) {
27
24
- pkt = g_queue_pop_tail(&conn->primary_list);
28
+ event_notifier_init_fd(svq_kick, svq_kick_fd);
25
+ pkt = g_queue_pop_head(&conn->primary_list);
29
/*
26
switch (conn->ip_proto) {
30
* event_notifier_set_handler already checks for guest's notifications if
27
case IPPROTO_TCP:
31
* they arrive at the new file descriptor in the switch, so there is no
28
result = g_queue_find_custom(&conn->secondary_list,
32
* need to explicitly check for them.
29
@@ -XXX,XX +XXX,XX @@ static void colo_compare_connection(void *opaque, void *user_data)
33
*/
30
* until next comparison.
34
if (poll_start) {
31
*/
35
- event_notifier_init_fd(svq_kick, svq_kick_fd);
32
trace_colo_compare_main("packet different");
36
event_notifier_set(svq_kick);
33
- g_queue_push_tail(&conn->primary_list, pkt);
37
event_notifier_set_handler(svq_kick, vhost_handle_guest_kick_notifier);
34
+ g_queue_push_head(&conn->primary_list, pkt);
38
}
35
/* TODO: colo_notify_checkpoint();*/
39
@@ -XXX,XX +XXX,XX @@ void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev,
36
break;
40
*/
37
}
41
void vhost_svq_stop(VhostShadowVirtqueue *svq)
42
{
43
- event_notifier_set_handler(&svq->svq_kick, NULL);
44
+ vhost_svq_set_svq_kick_fd(svq, VHOST_FILE_UNBIND);
45
g_autofree VirtQueueElement *next_avail_elem = NULL;
46
47
if (!svq->vq) {
38
--
48
--
39
2.7.4
49
2.7.4
40
50
41
51
diff view generated by jsdifflib
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
1
From: Eugenio Pérez <eperezma@redhat.com>
2
2
3
Cc: berrange@redhat.com
3
Reduce code duplication.
4
Cc: kraxel@redhat.com
4
5
Cc: pbonzini@redhat.com
5
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
6
Cc: jasowang@redhat.com
6
Acked-by: Jason Wang <jasowang@redhat.com>
7
Cc: armbru@redhat.com
8
Cc: eblake@redhat.com
9
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
10
Reviewed-by: Markus Armbruster <armbru@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
8
---
13
include/qemu/sockets.h | 3 ++-
9
hw/virtio/vhost-vdpa.c | 17 ++++++++---------
14
net/net.c | 22 +++++++++++++++++-----
10
1 file changed, 8 insertions(+), 9 deletions(-)
15
net/socket.c | 22 +++++++++++++++-------
16
3 files changed, 34 insertions(+), 13 deletions(-)
17
11
18
diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
12
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
19
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
20
--- a/include/qemu/sockets.h
14
--- a/hw/virtio/vhost-vdpa.c
21
+++ b/include/qemu/sockets.h
15
+++ b/hw/virtio/vhost-vdpa.c
22
@@ -XXX,XX +XXX,XX @@ void socket_listen_cleanup(int fd, Error **errp);
16
@@ -XXX,XX +XXX,XX @@ static int vhost_vdpa_svq_set_fds(struct vhost_dev *dev,
23
int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp);
24
25
/* Old, ipv4 only bits. Don't use for new code. */
26
-int parse_host_port(struct sockaddr_in *saddr, const char *str);
27
+int parse_host_port(struct sockaddr_in *saddr, const char *str,
28
+ Error **errp);
29
int socket_init(void);
30
31
/**
17
/**
32
diff --git a/net/net.c b/net/net.c
18
* Unmap a SVQ area in the device
33
index XXXXXXX..XXXXXXX 100644
19
*/
34
--- a/net/net.c
20
-static void vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v,
35
+++ b/net/net.c
21
- const DMAMap *needle)
36
@@ -XXX,XX +XXX,XX @@ static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
22
+static void vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v, hwaddr addr)
37
return 0;
23
{
24
- const DMAMap *result = vhost_iova_tree_find_iova(v->iova_tree, needle);
25
+ const DMAMap needle = {
26
+ .translated_addr = addr,
27
+ };
28
+ const DMAMap *result = vhost_iova_tree_find_iova(v->iova_tree, &needle);
29
hwaddr size;
30
int r;
31
32
@@ -XXX,XX +XXX,XX @@ static void vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v,
33
static void vhost_vdpa_svq_unmap_rings(struct vhost_dev *dev,
34
const VhostShadowVirtqueue *svq)
35
{
36
- DMAMap needle = {};
37
struct vhost_vdpa *v = dev->opaque;
38
struct vhost_vring_addr svq_addr;
39
40
vhost_svq_get_vring_addr(svq, &svq_addr);
41
42
- needle.translated_addr = svq_addr.desc_user_addr;
43
- vhost_vdpa_svq_unmap_ring(v, &needle);
44
+ vhost_vdpa_svq_unmap_ring(v, svq_addr.desc_user_addr);
45
46
- needle.translated_addr = svq_addr.used_user_addr;
47
- vhost_vdpa_svq_unmap_ring(v, &needle);
48
+ vhost_vdpa_svq_unmap_ring(v, svq_addr.used_user_addr);
38
}
49
}
39
50
40
-int parse_host_port(struct sockaddr_in *saddr, const char *str)
51
/**
41
+int parse_host_port(struct sockaddr_in *saddr, const char *str,
52
@@ -XXX,XX +XXX,XX @@ static bool vhost_vdpa_svq_map_rings(struct vhost_dev *dev,
42
+ Error **errp)
53
ok = vhost_vdpa_svq_map_ring(v, &device_region, errp);
43
{
54
if (unlikely(!ok)) {
44
char buf[512];
55
error_prepend(errp, "Cannot create vq device region: ");
45
struct hostent *he;
56
- vhost_vdpa_svq_unmap_ring(v, &driver_region);
46
@@ -XXX,XX +XXX,XX @@ int parse_host_port(struct sockaddr_in *saddr, const char *str)
57
+ vhost_vdpa_svq_unmap_ring(v, driver_region.translated_addr);
47
int port;
48
49
p = str;
50
- if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
51
+ if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
52
+ error_setg(errp, "host address '%s' doesn't contain ':' "
53
+ "separating host from port", str);
54
return -1;
55
+ }
56
saddr->sin_family = AF_INET;
57
if (buf[0] == '\0') {
58
saddr->sin_addr.s_addr = 0;
59
} else {
60
if (qemu_isdigit(buf[0])) {
61
- if (!inet_aton(buf, &saddr->sin_addr))
62
+ if (!inet_aton(buf, &saddr->sin_addr)) {
63
+ error_setg(errp, "host address '%s' is not a valid "
64
+ "IPv4 address", buf);
65
return -1;
66
+ }
67
} else {
68
- if ((he = gethostbyname(buf)) == NULL)
69
+ he = gethostbyname(buf);
70
+ if (he == NULL) {
71
+ error_setg(errp, "can't resolve host address '%s'", buf);
72
return - 1;
73
+ }
74
saddr->sin_addr = *(struct in_addr *)he->h_addr;
75
}
76
}
58
}
77
port = strtol(p, (char **)&r, 0);
59
addr->used_user_addr = device_region.iova;
78
- if (r == p)
79
+ if (r == p) {
80
+ error_setg(errp, "port number '%s' is invalid", p);
81
return -1;
82
+ }
83
saddr->sin_port = htons(port);
84
return 0;
85
}
86
diff --git a/net/socket.c b/net/socket.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/net/socket.c
89
+++ b/net/socket.c
90
@@ -XXX,XX +XXX,XX @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer,
91
*/
92
93
if (is_connected && mcast != NULL) {
94
- if (parse_host_port(&saddr, mcast) < 0) {
95
- error_setg(errp, "fd=%d failed parse_host_port()", fd);
96
+ if (parse_host_port(&saddr, mcast, errp) < 0) {
97
goto err;
98
}
99
/* must be bound */
100
@@ -XXX,XX +XXX,XX @@ static int net_socket_listen_init(NetClientState *peer,
101
NetSocketState *s;
102
struct sockaddr_in saddr;
103
int fd, ret;
104
+ Error *err = NULL;
105
106
- if (parse_host_port(&saddr, host_str) < 0)
107
+ if (parse_host_port(&saddr, host_str, &err) < 0) {
108
+ error_report_err(err);
109
return -1;
110
+ }
111
112
fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
113
if (fd < 0) {
114
@@ -XXX,XX +XXX,XX @@ static int net_socket_connect_init(NetClientState *peer,
115
struct sockaddr_in saddr;
116
Error *err = NULL;
117
118
- if (parse_host_port(&saddr, host_str) < 0)
119
+ if (parse_host_port(&saddr, host_str, &err) < 0) {
120
+ error_report_err(err);
121
return -1;
122
+ }
123
124
fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
125
if (fd < 0) {
126
@@ -XXX,XX +XXX,XX @@ static int net_socket_mcast_init(NetClientState *peer,
127
struct in_addr localaddr, *param_localaddr;
128
Error *err = NULL;
129
130
- if (parse_host_port(&saddr, host_str) < 0)
131
+ if (parse_host_port(&saddr, host_str, &err) < 0) {
132
+ error_report_err(err);
133
return -1;
134
+ }
135
136
if (localaddr_str != NULL) {
137
if (inet_aton(localaddr_str, &localaddr) == 0)
138
@@ -XXX,XX +XXX,XX @@ static int net_socket_udp_init(NetClientState *peer,
139
struct sockaddr_in laddr, raddr;
140
Error *err = NULL;
141
142
- if (parse_host_port(&laddr, lhost) < 0) {
143
+ if (parse_host_port(&laddr, lhost, &err) < 0) {
144
+ error_report_err(err);
145
return -1;
146
}
147
148
- if (parse_host_port(&raddr, rhost) < 0) {
149
+ if (parse_host_port(&raddr, rhost, &err) < 0) {
150
+ error_report_err(err);
151
return -1;
152
}
153
60
154
--
61
--
155
2.7.4
62
2.7.4
156
63
157
64
diff view generated by jsdifflib
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
1
From: Eugenio Pérez <eperezma@redhat.com>
2
2
3
pci_rocker_init() leaks a World when the name more than 9 chars,
3
It was easier to allow vhost_svq_add to handle the memory. Now that we
4
then return a negative value directly, doesn't make a correct
4
will allow qemu to add elements to a SVQ without the guest's knowledge,
5
cleanup. So add a new goto label to fix it.
5
it's better to handle it in the caller.
6
6
7
Cc: jasowang@redhat.com
7
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
8
Cc: jiri@resnulli.us
8
Acked-by: Jason Wang <jasowang@redhat.com>
9
Cc: armbru@redhat.com
10
Cc: f4bug@amsat.org
11
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
12
Reviewed-by: Markus Armbruster <armbru@redhat.com>
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
15
---
10
---
16
hw/net/rocker/rocker.c | 4 +++-
11
hw/virtio/vhost-shadow-virtqueue.c | 10 ++++------
17
1 file changed, 3 insertions(+), 1 deletion(-)
12
1 file changed, 4 insertions(+), 6 deletions(-)
18
13
19
diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c
14
diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
20
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/net/rocker/rocker.c
16
--- a/hw/virtio/vhost-shadow-virtqueue.c
22
+++ b/hw/net/rocker/rocker.c
17
+++ b/hw/virtio/vhost-shadow-virtqueue.c
23
@@ -XXX,XX +XXX,XX @@ static int pci_rocker_init(PCIDevice *dev)
18
@@ -XXX,XX +XXX,XX @@ static void vhost_svq_kick(VhostShadowVirtqueue *svq)
24
fprintf(stderr,
19
/**
25
"rocker: name too long; please shorten to at most %d chars\n",
20
* Add an element to a SVQ.
26
MAX_ROCKER_NAME_LEN);
21
*
27
- return -EINVAL;
22
- * The caller must check that there is enough slots for the new element. It
28
+ err = -EINVAL;
23
- * takes ownership of the element: In case of failure not ENOSPC, it is free.
29
+ goto err_name_too_long;
24
- *
25
* Return -EINVAL if element is invalid, -ENOSPC if dev queue is full
26
*/
27
int vhost_svq_add(VhostShadowVirtqueue *svq, const struct iovec *out_sg,
28
@@ -XXX,XX +XXX,XX @@ int vhost_svq_add(VhostShadowVirtqueue *svq, const struct iovec *out_sg,
29
30
ok = vhost_svq_add_split(svq, out_sg, out_num, in_sg, in_num, &qemu_head);
31
if (unlikely(!ok)) {
32
- g_free(elem);
33
return -EINVAL;
30
}
34
}
31
35
32
if (memcmp(&r->fp_start_macaddr, &zero, sizeof(zero)) == 0) {
36
@@ -XXX,XX +XXX,XX @@ static void vhost_handle_guest_kick(VhostShadowVirtqueue *svq)
33
@@ -XXX,XX +XXX,XX @@ static int pci_rocker_init(PCIDevice *dev)
37
virtio_queue_set_notification(svq->vq, false);
34
38
35
return 0;
39
while (true) {
36
40
- VirtQueueElement *elem;
37
+err_name_too_long:
41
+ g_autofree VirtQueueElement *elem;
38
err_duplicate:
42
int r;
39
rocker_msix_uninit(r);
43
40
err_msix_init:
44
if (svq->next_guest_avail_elem) {
45
@@ -XXX,XX +XXX,XX @@ static void vhost_handle_guest_kick(VhostShadowVirtqueue *svq)
46
* queue the current guest descriptor and ignore kicks
47
* until some elements are used.
48
*/
49
- svq->next_guest_avail_elem = elem;
50
+ svq->next_guest_avail_elem = g_steal_pointer(&elem);
51
}
52
53
/* VQ is full or broken, just return and ignore kicks */
54
return;
55
}
56
+ /* elem belongs to SVQ or external caller now */
57
+ elem = NULL;
58
}
59
60
virtio_queue_set_notification(svq->vq, true);
41
--
61
--
42
2.7.4
62
2.7.4
43
63
44
64
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Eugenio Pérez <eperezma@redhat.com>
2
2
3
Because vnet_hdr have a offset to net packet, we must add it when use
3
Since we're going to allow SVQ to add elements without the guest's
4
virtio-net.
4
knowledge and without its own VirtQueueElement, it's easier to check if
5
an element is a valid head checking a different thing than the
6
VirtQueueElement.
5
7
6
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
8
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
9
Acked-by: Jason Wang <jasowang@redhat.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
11
---
9
net/filter-rewriter.c | 6 ++++--
12
hw/virtio/vhost-shadow-virtqueue.c | 3 ++-
10
1 file changed, 4 insertions(+), 2 deletions(-)
13
1 file changed, 2 insertions(+), 1 deletion(-)
11
14
12
diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c
15
diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
13
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
14
--- a/net/filter-rewriter.c
17
--- a/hw/virtio/vhost-shadow-virtqueue.c
15
+++ b/net/filter-rewriter.c
18
+++ b/hw/virtio/vhost-shadow-virtqueue.c
16
@@ -XXX,XX +XXX,XX @@ static int handle_primary_tcp_pkt(NetFilterState *nf,
19
@@ -XXX,XX +XXX,XX @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,
17
/* handle packets to the secondary from the primary */
20
return NULL;
18
tcp_pkt->th_ack = htonl(ntohl(tcp_pkt->th_ack) + conn->offset);
19
20
- net_checksum_calculate((uint8_t *)pkt->data, pkt->size);
21
+ net_checksum_calculate((uint8_t *)pkt->data + pkt->vnet_hdr_len,
22
+ pkt->size - pkt->vnet_hdr_len);
23
}
24
}
21
}
25
22
26
@@ -XXX,XX +XXX,XX @@ static int handle_secondary_tcp_pkt(NetFilterState *nf,
23
- if (unlikely(!svq->desc_state[used_elem.id].elem)) {
27
/* handle packets to the primary from the secondary*/
24
+ if (unlikely(!svq->desc_state[used_elem.id].ndescs)) {
28
tcp_pkt->th_seq = htonl(ntohl(tcp_pkt->th_seq) - conn->offset);
25
qemu_log_mask(LOG_GUEST_ERROR,
29
26
"Device %s says index %u is used, but it was not available",
30
- net_checksum_calculate((uint8_t *)pkt->data, pkt->size);
27
svq->vdev->name, used_elem.id);
31
+ net_checksum_calculate((uint8_t *)pkt->data + pkt->vnet_hdr_len,
28
@@ -XXX,XX +XXX,XX @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,
32
+ pkt->size - pkt->vnet_hdr_len);
33
}
34
}
29
}
35
30
31
num = svq->desc_state[used_elem.id].ndescs;
32
+ svq->desc_state[used_elem.id].ndescs = 0;
33
last_used_chain = vhost_svq_last_desc_of_chain(svq, num, used_elem.id);
34
svq->desc_next[last_used_chain] = svq->free_head;
35
svq->free_head = used_elem.id;
36
--
36
--
37
2.7.4
37
2.7.4
38
38
39
39
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Eugenio Pérez <eperezma@redhat.com>
2
2
3
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
3
As discussed in previous series [1], this memory barrier is useless with
4
the atomic read of used idx at vhost_svq_more_used. Deleting it.
5
6
[1] https://lists.nongnu.org/archive/html/qemu-devel/2022-07/msg02616.html
7
8
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
9
Acked-by: Jason Wang <jasowang@redhat.com>
4
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
5
---
11
---
6
net/colo-compare.c | 59 ++++++++++++++++++++++++++++--------------------------
12
hw/virtio/vhost-shadow-virtqueue.c | 3 ---
7
1 file changed, 31 insertions(+), 28 deletions(-)
13
1 file changed, 3 deletions(-)
8
14
9
diff --git a/net/colo-compare.c b/net/colo-compare.c
15
diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
10
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
11
--- a/net/colo-compare.c
17
--- a/hw/virtio/vhost-shadow-virtqueue.c
12
+++ b/net/colo-compare.c
18
+++ b/hw/virtio/vhost-shadow-virtqueue.c
13
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ size_t vhost_svq_poll(VhostShadowVirtqueue *svq)
14
#define REGULAR_PACKET_CHECK_MS 3000
20
if (unlikely(g_get_monotonic_time() - start_us > 10e6)) {
15
21
return 0;
16
/*
22
}
17
- + CompareState ++
23
-
18
- | |
24
- /* Make sure we read new used_idx */
19
- +---------------+ +---------------+ +---------------+
25
- smp_rmb();
20
- |conn list +--->conn +--------->conn |
26
} while (true);
21
- +---------------+ +---------------+ +---------------+
27
}
22
- | | | | | |
23
- +---------------+ +---v----+ +---v----+ +---v----+ +---v----+
24
- |primary | |secondary |primary | |secondary
25
- |packet | |packet + |packet | |packet +
26
- +--------+ +--------+ +--------+ +--------+
27
- | | | |
28
- +---v----+ +---v----+ +---v----+ +---v----+
29
- |primary | |secondary |primary | |secondary
30
- |packet | |packet + |packet | |packet +
31
- +--------+ +--------+ +--------+ +--------+
32
- | | | |
33
- +---v----+ +---v----+ +---v----+ +---v----+
34
- |primary | |secondary |primary | |secondary
35
- |packet | |packet + |packet | |packet +
36
- +--------+ +--------+ +--------+ +--------+
37
-*/
38
+ * + CompareState ++
39
+ * | |
40
+ * +---------------+ +---------------+ +---------------+
41
+ * | conn list + - > conn + ------- > conn + -- > ......
42
+ * +---------------+ +---------------+ +---------------+
43
+ * | | | | | |
44
+ * +---------------+ +---v----+ +---v----+ +---v----+ +---v----+
45
+ * |primary | |secondary |primary | |secondary
46
+ * |packet | |packet + |packet | |packet +
47
+ * +--------+ +--------+ +--------+ +--------+
48
+ * | | | |
49
+ * +---v----+ +---v----+ +---v----+ +---v----+
50
+ * |primary | |secondary |primary | |secondary
51
+ * |packet | |packet + |packet | |packet +
52
+ * +--------+ +--------+ +--------+ +--------+
53
+ * | | | |
54
+ * +---v----+ +---v----+ +---v----+ +---v----+
55
+ * |primary | |secondary |primary | |secondary
56
+ * |packet | |packet + |packet | |packet +
57
+ * +--------+ +--------+ +--------+ +--------+
58
+ */
59
typedef struct CompareState {
60
Object parent;
61
62
@@ -XXX,XX +XXX,XX @@ typedef struct CompareState {
63
SocketReadState sec_rs;
64
bool vnet_hdr;
65
66
- /* connection list: the connections belonged to this NIC could be found
67
- * in this list.
68
- * element type: Connection
69
+ /*
70
+ * Record the connection that through the NIC
71
+ * Element type: Connection
72
*/
73
GQueue conn_list;
74
- /* hashtable to save connection */
75
+ /* Record the connection without repetition */
76
GHashTable *connection_track_table;
77
- /* compare thread, a thread for each NIC */
78
+ /* This thread just do packet compare job */
79
QemuThread thread;
80
81
GMainContext *worker_context;
82
@@ -XXX,XX +XXX,XX @@ static int colo_old_packet_check_one_conn(Connection *conn,
83
(GCompareFunc)colo_old_packet_check_one);
84
85
if (result) {
86
- /* do checkpoint will flush old packet */
87
- /* TODO: colo_notify_checkpoint();*/
88
+ /* Do checkpoint will flush old packet */
89
+ /*
90
+ * TODO: Notify colo frame to do checkpoint.
91
+ * colo_compare_inconsistent_notify();
92
+ */
93
return 0;
94
}
95
28
96
--
29
--
97
2.7.4
30
2.7.4
98
31
99
32
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Eugenio Pérez <eperezma@redhat.com>
2
2
3
When network is busy, some tcp options(like sack) will unpredictable
3
Since QEMU will be able to inject new elements on CVQ to restore the
4
occur in primary side or secondary side. it will make packet size
4
state, we need not to depend on a VirtQueueElement to know if a new
5
not same, but the two packet's payload is identical. colo just
5
element has been used by the device or not. Instead of check that, check
6
care about packet payload, so we skip the option field.
6
if there are new elements only using used idx on vhost_svq_flush.
7
7
8
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
8
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
9
Acked-by: Jason Wang <jasowang@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
11
---
11
net/colo-compare.c | 39 +++++++++++++++++++++++++++------------
12
hw/virtio/vhost-shadow-virtqueue.c | 11 +++++++----
12
1 file changed, 27 insertions(+), 12 deletions(-)
13
1 file changed, 7 insertions(+), 4 deletions(-)
13
14
14
diff --git a/net/colo-compare.c b/net/colo-compare.c
15
diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/net/colo-compare.c
17
--- a/hw/virtio/vhost-shadow-virtqueue.c
17
+++ b/net/colo-compare.c
18
+++ b/hw/virtio/vhost-shadow-virtqueue.c
18
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode)
19
@@ -XXX,XX +XXX,XX @@ static void vhost_svq_flush(VhostShadowVirtqueue *svq,
19
* return: 0 means packet same
20
size_t vhost_svq_poll(VhostShadowVirtqueue *svq)
20
* > 0 || < 0 means packet different
21
*/
22
-static int colo_packet_compare_common(Packet *ppkt, Packet *spkt, int offset)
23
+static int colo_packet_compare_common(Packet *ppkt,
24
+ Packet *spkt,
25
+ int poffset,
26
+ int soffset)
27
{
21
{
28
if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) {
22
int64_t start_us = g_get_monotonic_time();
29
char pri_ip_src[20], pri_ip_dst[20], sec_ip_src[20], sec_ip_dst[20];
23
+ uint32_t len;
30
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_common(Packet *ppkt, Packet *spkt, int offset)
31
sec_ip_src, sec_ip_dst);
32
}
33
34
- offset = ppkt->vnet_hdr_len + offset;
35
+ poffset = ppkt->vnet_hdr_len + poffset;
36
+ soffset = ppkt->vnet_hdr_len + soffset;
37
38
- if (ppkt->size == spkt->size) {
39
- return memcmp(ppkt->data + offset,
40
- spkt->data + offset,
41
- spkt->size - offset);
42
+ if (ppkt->size - poffset == spkt->size - soffset) {
43
+ return memcmp(ppkt->data + poffset,
44
+ spkt->data + soffset,
45
+ spkt->size - soffset);
46
} else {
47
trace_colo_compare_main("Net packet size are not the same");
48
return -1;
49
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_tcp(Packet *spkt, Packet *ppkt)
50
* so we just need skip this field.
51
*/
52
if (ptcp->th_off > 5) {
53
- ptrdiff_t tcp_offset;
54
+ ptrdiff_t ptcp_offset, stcp_offset;
55
56
- tcp_offset = ppkt->transport_header - (uint8_t *)ppkt->data
57
- + (ptcp->th_off * 4) - ppkt->vnet_hdr_len;
58
- res = colo_packet_compare_common(ppkt, spkt, tcp_offset);
59
+ ptcp_offset = ppkt->transport_header - (uint8_t *)ppkt->data
60
+ + (ptcp->th_off * 4) - ppkt->vnet_hdr_len;
61
+ stcp_offset = spkt->transport_header - (uint8_t *)spkt->data
62
+ + (stcp->th_off * 4) - spkt->vnet_hdr_len;
63
+
24
+
64
+ /*
25
do {
65
+ * When network is busy, some tcp options(like sack) will unpredictable
26
- uint32_t len;
66
+ * occur in primary side or secondary side. it will make packet size
27
- VirtQueueElement *elem = vhost_svq_get_buf(svq, &len);
67
+ * not same, but the two packet's payload is identical. colo just
28
- if (elem) {
68
+ * care about packet payload, so we skip the option field.
29
- return len;
69
+ */
30
+ if (vhost_svq_more_used(svq)) {
70
+ res = colo_packet_compare_common(ppkt, spkt, ptcp_offset, stcp_offset);
31
+ break;
71
} else if (ptcp->th_sum == stcp->th_sum) {
32
}
72
- res = colo_packet_compare_common(ppkt, spkt, ETH_HLEN);
33
73
+ res = colo_packet_compare_common(ppkt, spkt, ETH_HLEN, ETH_HLEN);
34
if (unlikely(g_get_monotonic_time() - start_us > 10e6)) {
74
} else {
35
return 0;
75
res = -1;
36
}
76
}
37
} while (true);
77
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt)
38
+
78
* the ip payload here.
39
+ vhost_svq_get_buf(svq, &len);
79
*/
40
+ return len;
80
ret = colo_packet_compare_common(ppkt, spkt,
81
+ network_header_length + ETH_HLEN,
82
network_header_length + ETH_HLEN);
83
84
if (ret) {
85
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_icmp(Packet *spkt, Packet *ppkt)
86
* the ip payload here.
87
*/
88
if (colo_packet_compare_common(ppkt, spkt,
89
+ network_header_length + ETH_HLEN,
90
network_header_length + ETH_HLEN)) {
91
trace_colo_compare_icmp_miscompare("primary pkt size",
92
ppkt->size);
93
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_other(Packet *spkt, Packet *ppkt)
94
sec_ip_src, sec_ip_dst);
95
}
96
97
- return colo_packet_compare_common(ppkt, spkt, 0);
98
+ return colo_packet_compare_common(ppkt, spkt, 0, 0);
99
}
41
}
100
42
101
static int colo_old_packet_check_one(Packet *pkt, int64_t *check_time)
43
/**
102
--
44
--
103
2.7.4
45
2.7.4
104
46
105
47
diff view generated by jsdifflib
1
From: Kamil Rytarowski <n54@gmx.com>
1
From: Eugenio Pérez <eperezma@redhat.com>
2
2
3
SunOS defines SEC in <sys/time.h> as 1 (commonly used time symbols).
3
This is used by the backend to perform actions before the device is
4
started.
4
5
5
This fixes build on SmartOS (Joyent).
6
In particular, vdpa net use it to map CVQ buffers to the device, so it
7
can send control commands using them.
6
8
7
Patch cherry-picked from pkgsrc by jperkin (Joyent).
9
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
8
10
Acked-by: Jason Wang <jasowang@redhat.com>
9
Signed-off-by: Kamil Rytarowski <n54@gmx.com>
10
Reviewed-by: Dmitry Fleytman <dmitry@daynix.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
12
---
13
hw/net/e1000.c | 4 ++--
13
hw/net/vhost_net.c | 7 +++++++
14
hw/net/e1000_regs.h | 2 +-
14
include/net/net.h | 2 ++
15
hw/net/e1000e_core.c | 2 +-
15
2 files changed, 9 insertions(+)
16
hw/net/e1000x_common.h | 2 +-
17
4 files changed, 5 insertions(+), 5 deletions(-)
18
16
19
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
17
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
20
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/net/e1000.c
19
--- a/hw/net/vhost_net.c
22
+++ b/hw/net/e1000.c
20
+++ b/hw/net/vhost_net.c
23
@@ -XXX,XX +XXX,XX @@ static uint32_t (*macreg_readops[])(E1000State *, int) = {
21
@@ -XXX,XX +XXX,XX @@ static int vhost_net_start_one(struct vhost_net *net,
24
getreg(TADV), getreg(ITR), getreg(FCRUC), getreg(IPAV),
22
struct vhost_vring_file file = { };
25
getreg(WUC), getreg(WUS), getreg(SCC), getreg(ECOL),
23
int r;
26
getreg(MCC), getreg(LATECOL), getreg(COLC), getreg(DC),
24
27
- getreg(TNCRS), getreg(SEC), getreg(CEXTERR), getreg(RLEC),
25
+ if (net->nc->info->start) {
28
+ getreg(TNCRS), getreg(SEQEC), getreg(CEXTERR), getreg(RLEC),
26
+ r = net->nc->info->start(net->nc);
29
getreg(XONRXC), getreg(XONTXC), getreg(XOFFRXC), getreg(XOFFTXC),
27
+ if (r < 0) {
30
getreg(RFC), getreg(RJC), getreg(RNBC), getreg(TSCTFC),
28
+ return r;
31
getreg(MGTPRC), getreg(MGTPDC), getreg(MGTPTC), getreg(GORCL),
29
+ }
32
@@ -XXX,XX +XXX,XX @@ static const uint8_t mac_reg_access[0x8000] = {
30
+ }
33
[FFLT] = markflag(MAC), [FFMT] = markflag(MAC),
31
+
34
[SCC] = markflag(MAC), [FCRUC] = markflag(MAC),
32
r = vhost_dev_enable_notifiers(&net->dev, dev);
35
[LATECOL] = markflag(MAC), [COLC] = markflag(MAC),
33
if (r < 0) {
36
- [SEC] = markflag(MAC), [CEXTERR] = markflag(MAC),
34
goto fail_notifiers;
37
+ [SEQEC] = markflag(MAC), [CEXTERR] = markflag(MAC),
35
diff --git a/include/net/net.h b/include/net/net.h
38
[XONTXC] = markflag(MAC), [XOFFRXC] = markflag(MAC),
39
[RJC] = markflag(MAC), [RNBC] = markflag(MAC),
40
[MGTPDC] = markflag(MAC), [MGTPTC] = markflag(MAC),
41
diff --git a/hw/net/e1000_regs.h b/hw/net/e1000_regs.h
42
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/net/e1000_regs.h
37
--- a/include/net/net.h
44
+++ b/hw/net/e1000_regs.h
38
+++ b/include/net/net.h
45
@@ -XXX,XX +XXX,XX @@
39
@@ -XXX,XX +XXX,XX @@ typedef struct NICConf {
46
#define E1000_COLC 0x04028 /* Collision Count - R/clr */
40
47
#define E1000_DC 0x04030 /* Defer Count - R/clr */
41
typedef void (NetPoll)(NetClientState *, bool enable);
48
#define E1000_TNCRS 0x04034 /* TX-No CRS - R/clr */
42
typedef bool (NetCanReceive)(NetClientState *);
49
-#define E1000_SEC 0x04038 /* Sequence Error Count - R/clr */
43
+typedef int (NetStart)(NetClientState *);
50
+#define E1000_SEQEC 0x04038 /* Sequence Error Count - R/clr */
44
typedef ssize_t (NetReceive)(NetClientState *, const uint8_t *, size_t);
51
#define E1000_CEXTERR 0x0403C /* Carrier Extension Error Count - R/clr */
45
typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int);
52
#define E1000_RLEC 0x04040 /* Receive Length Error Count - R/clr */
46
typedef void (NetCleanup) (NetClientState *);
53
#define E1000_XONRXC 0x04048 /* XON RX Count - R/clr */
47
@@ -XXX,XX +XXX,XX @@ typedef struct NetClientInfo {
54
diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
48
NetReceive *receive_raw;
55
index XXXXXXX..XXXXXXX 100644
49
NetReceiveIOV *receive_iov;
56
--- a/hw/net/e1000e_core.c
50
NetCanReceive *can_receive;
57
+++ b/hw/net/e1000e_core.c
51
+ NetStart *start;
58
@@ -XXX,XX +XXX,XX @@ static uint32_t (*e1000e_macreg_readops[])(E1000ECore *, int) = {
52
NetCleanup *cleanup;
59
e1000e_getreg(RDLEN0),
53
LinkStatusChanged *link_status_changed;
60
e1000e_getreg(RDH1),
54
QueryRxFilter *query_rx_filter;
61
e1000e_getreg(LATECOL),
62
- e1000e_getreg(SEC),
63
+ e1000e_getreg(SEQEC),
64
e1000e_getreg(XONTXC),
65
e1000e_getreg(WUS),
66
e1000e_getreg(GORCL),
67
diff --git a/hw/net/e1000x_common.h b/hw/net/e1000x_common.h
68
index XXXXXXX..XXXXXXX 100644
69
--- a/hw/net/e1000x_common.h
70
+++ b/hw/net/e1000x_common.h
71
@@ -XXX,XX +XXX,XX @@ enum {
72
defreg(VFTA), defreg(VET), defreg(RDTR), defreg(RADV),
73
defreg(TADV), defreg(ITR), defreg(SCC), defreg(ECOL),
74
defreg(MCC), defreg(LATECOL), defreg(COLC), defreg(DC),
75
- defreg(TNCRS), defreg(SEC), defreg(CEXTERR), defreg(RLEC),
76
+ defreg(TNCRS), defreg(SEQEC), defreg(CEXTERR), defreg(RLEC),
77
defreg(XONRXC), defreg(XONTXC), defreg(XOFFRXC), defreg(XOFFTXC),
78
defreg(FCRUC), defreg(AIT), defreg(TDFH), defreg(TDFT),
79
defreg(TDFHS), defreg(TDFTS), defreg(TDFPC), defreg(WUC),
80
--
55
--
81
2.7.4
56
2.7.4
82
57
83
58
diff view generated by jsdifflib
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
1
From: Eugenio Pérez <eperezma@redhat.com>
2
2
3
In net_socket_fd_init(), the 'default' case is odd: it warns,
3
Used by the backend to perform actions after the device is stopped.
4
then continues as if the socket type was SOCK_STREAM. The
5
comment explains "this could be a eg. a pty", but that makes
6
no sense. If @fd really was a pty, getsockopt() would fail
7
with ENOTSOCK. If @fd was a socket, but neither SOCK_DGRAM nor
8
SOCK_STREAM. It should not be treated as if it was SOCK_STREAM.
9
4
10
Turn this case into an Error. If there is a genuine reason to
5
In particular, vdpa net use it to unmap CVQ buffers to the device,
11
support something like SOCK_RAW, it should be explicitly
6
cleaning the actions performed in prepare().
12
handled.
13
7
14
Cc: jasowang@redhat.com
8
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
15
Cc: armbru@redhat.com
9
Acked-by: Jason Wang <jasowang@redhat.com>
16
Cc: berrange@redhat.com
17
Cc: armbru@redhat.com
18
Cc: eblake@redhat.com
19
Suggested-by: Markus Armbruster <armbru@redhat.com>
20
Suggested-by: Daniel P. Berrange <berrange@redhat.com>
21
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
22
Reviewed-by: Markus Armbruster <armbru@redhat.com>
23
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
24
---
11
---
25
net/socket.c | 6 +++---
12
hw/net/vhost_net.c | 3 +++
26
1 file changed, 3 insertions(+), 3 deletions(-)
13
include/net/net.h | 2 ++
14
2 files changed, 5 insertions(+)
27
15
28
diff --git a/net/socket.c b/net/socket.c
16
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
29
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
30
--- a/net/socket.c
18
--- a/hw/net/vhost_net.c
31
+++ b/net/socket.c
19
+++ b/hw/net/vhost_net.c
32
@@ -XXX,XX +XXX,XX @@ static NetSocketState *net_socket_fd_init(NetClientState *peer,
20
@@ -XXX,XX +XXX,XX @@ static void vhost_net_stop_one(struct vhost_net *net,
33
case SOCK_STREAM:
21
net->nc->info->poll(net->nc, true);
34
return net_socket_fd_init_stream(peer, model, name, fd, is_connected);
35
default:
36
- /* who knows ... this could be a eg. a pty, do warn and continue as stream */
37
- fprintf(stderr, "qemu: warning: socket type=%d for fd=%d is not SOCK_DGRAM or SOCK_STREAM\n", so_type, fd);
38
- return net_socket_fd_init_stream(peer, model, name, fd, is_connected);
39
+ error_report("socket type=%d for fd=%d must be either"
40
+ " SOCK_DGRAM or SOCK_STREAM", so_type, fd);
41
+ closesocket(fd);
42
}
22
}
43
return NULL;
23
vhost_dev_stop(&net->dev, dev);
24
+ if (net->nc->info->stop) {
25
+ net->nc->info->stop(net->nc);
26
+ }
27
vhost_dev_disable_notifiers(&net->dev, dev);
44
}
28
}
29
30
diff --git a/include/net/net.h b/include/net/net.h
31
index XXXXXXX..XXXXXXX 100644
32
--- a/include/net/net.h
33
+++ b/include/net/net.h
34
@@ -XXX,XX +XXX,XX @@ typedef struct NICConf {
35
typedef void (NetPoll)(NetClientState *, bool enable);
36
typedef bool (NetCanReceive)(NetClientState *);
37
typedef int (NetStart)(NetClientState *);
38
+typedef void (NetStop)(NetClientState *);
39
typedef ssize_t (NetReceive)(NetClientState *, const uint8_t *, size_t);
40
typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int);
41
typedef void (NetCleanup) (NetClientState *);
42
@@ -XXX,XX +XXX,XX @@ typedef struct NetClientInfo {
43
NetReceiveIOV *receive_iov;
44
NetCanReceive *can_receive;
45
NetStart *start;
46
+ NetStop *stop;
47
NetCleanup *cleanup;
48
LinkStatusChanged *link_status_changed;
49
QueryRxFilter *query_rx_filter;
45
--
50
--
46
2.7.4
51
2.7.4
47
52
48
53
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Eugenio Pérez <eperezma@redhat.com>
2
2
3
My Fujitsu mail account will be disabled soon, update the mail info
3
Next patches will add a new info callback to restore NIC status through
4
to my private mail.
4
CVQ. Since only the CVQ vhost device is needed, create it with a new
5
NetClientInfo.
5
6
6
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
7
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
8
Acked-by: Jason Wang <jasowang@redhat.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
10
---
9
MAINTAINERS | 2 +-
11
net/vhost-vdpa.c | 12 +++++++++++-
10
1 file changed, 1 insertion(+), 1 deletion(-)
12
1 file changed, 11 insertions(+), 1 deletion(-)
11
13
12
diff --git a/MAINTAINERS b/MAINTAINERS
14
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/MAINTAINERS
16
--- a/net/vhost-vdpa.c
15
+++ b/MAINTAINERS
17
+++ b/net/vhost-vdpa.c
16
@@ -XXX,XX +XXX,XX @@ F: include/migration/failover.h
18
@@ -XXX,XX +XXX,XX @@ static bool vhost_vdpa_net_cvq_map_elem(VhostVDPAState *s,
17
F: docs/COLO-FT.txt
19
return true;
18
20
}
19
COLO Proxy
21
20
-M: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
22
+static NetClientInfo net_vhost_vdpa_cvq_info = {
21
+M: Zhang Chen <zhangckid@gmail.com>
23
+ .type = NET_CLIENT_DRIVER_VHOST_VDPA,
22
M: Li Zhijian <lizhijian@cn.fujitsu.com>
24
+ .size = sizeof(VhostVDPAState),
23
S: Supported
25
+ .receive = vhost_vdpa_receive,
24
F: docs/colo-proxy.txt
26
+ .cleanup = vhost_vdpa_cleanup,
27
+ .has_vnet_hdr = vhost_vdpa_has_vnet_hdr,
28
+ .has_ufo = vhost_vdpa_has_ufo,
29
+ .check_peer_type = vhost_vdpa_check_peer_type,
30
+};
31
+
32
/**
33
* Do not forward commands not supported by SVQ. Otherwise, the device could
34
* accept it and qemu would not know how to update the device model.
35
@@ -XXX,XX +XXX,XX @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer,
36
nc = qemu_new_net_client(&net_vhost_vdpa_info, peer, device,
37
name);
38
} else {
39
- nc = qemu_new_net_control_client(&net_vhost_vdpa_info, peer,
40
+ nc = qemu_new_net_control_client(&net_vhost_vdpa_cvq_info, peer,
41
device, name);
42
}
43
snprintf(nc->info_str, sizeof(nc->info_str), TYPE_VHOST_VDPA);
25
--
44
--
26
2.7.4
45
2.7.4
27
46
28
47
diff view generated by jsdifflib
1
From: Matt Parker <mtparkr@gmail.com>
1
From: Eugenio Pérez <eperezma@redhat.com>
2
2
3
Both io and memory use the same mmio functions in the rtl8139 device.
3
As this series will reuse them to restore the device state at the end of
4
This patch removes the separate MemoryRegionOps and old_mmio accessors
4
a migration (or a device start), let's allocate only once at the device
5
for memory, and replaces it with an alias to the io memory region.
5
start so we don't duplicate their map and unmap.
6
6
7
Signed-off-by: Matt Parker <mtparkr@gmail.com>
7
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
8
Acked-by: Jason Wang <jasowang@redhat.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
10
---
10
hw/net/rtl8139.c | 53 +++--------------------------------------------------
11
net/vhost-vdpa.c | 123 ++++++++++++++++++++++++++-----------------------------
11
1 file changed, 3 insertions(+), 50 deletions(-)
12
1 file changed, 58 insertions(+), 65 deletions(-)
12
13
13
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
14
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/net/rtl8139.c
16
--- a/net/vhost-vdpa.c
16
+++ b/hw/net/rtl8139.c
17
+++ b/net/vhost-vdpa.c
17
@@ -XXX,XX +XXX,XX @@ static uint32_t rtl8139_io_readl(void *opaque, uint8_t addr)
18
@@ -XXX,XX +XXX,XX @@ static size_t vhost_vdpa_net_cvq_cmd_page_len(void)
18
19
return ROUND_UP(vhost_vdpa_net_cvq_cmd_len(), qemu_real_host_page_size());
19
/* */
20
}
20
21
21
-static void rtl8139_mmio_writeb(void *opaque, hwaddr addr, uint32_t val)
22
-/** Copy and map a guest buffer. */
22
-{
23
-static bool vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v,
23
- rtl8139_io_writeb(opaque, addr & 0xFF, val);
24
- const struct iovec *out_data,
24
-}
25
- size_t out_num, size_t data_len, void *buf,
26
- size_t *written, bool write)
27
+/** Map CVQ buffer. */
28
+static int vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, void *buf, size_t size,
29
+ bool write)
30
{
31
DMAMap map = {};
32
int r;
33
34
- if (unlikely(!data_len)) {
35
- qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid legnth of %s buffer\n",
36
- __func__, write ? "in" : "out");
37
- return false;
38
- }
25
-
39
-
26
-static void rtl8139_mmio_writew(void *opaque, hwaddr addr, uint32_t val)
40
- *written = iov_to_buf(out_data, out_num, 0, buf, data_len);
27
-{
41
map.translated_addr = (hwaddr)(uintptr_t)buf;
28
- rtl8139_io_writew(opaque, addr & 0xFF, val);
42
- map.size = vhost_vdpa_net_cvq_cmd_page_len() - 1;
29
-}
43
+ map.size = size - 1;
44
map.perm = write ? IOMMU_RW : IOMMU_RO,
45
r = vhost_iova_tree_map_alloc(v->iova_tree, &map);
46
if (unlikely(r != IOVA_OK)) {
47
error_report("Cannot map injected element");
48
- return false;
49
+ return r;
50
}
51
52
r = vhost_vdpa_dma_map(v, map.iova, vhost_vdpa_net_cvq_cmd_page_len(), buf,
53
@@ -XXX,XX +XXX,XX @@ static bool vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v,
54
goto dma_map_err;
55
}
56
57
- return true;
58
+ return 0;
59
60
dma_map_err:
61
vhost_iova_tree_remove(v->iova_tree, map);
62
- return false;
63
+ return r;
64
}
65
66
-/**
67
- * Copy the guest element into a dedicated buffer suitable to be sent to NIC
68
- *
69
- * @iov: [0] is the out buffer, [1] is the in one
70
- */
71
-static bool vhost_vdpa_net_cvq_map_elem(VhostVDPAState *s,
72
- VirtQueueElement *elem,
73
- struct iovec *iov)
74
+static int vhost_vdpa_net_cvq_start(NetClientState *nc)
75
{
76
- size_t in_copied;
77
- bool ok;
78
+ VhostVDPAState *s;
79
+ int r;
80
81
- iov[0].iov_base = s->cvq_cmd_out_buffer;
82
- ok = vhost_vdpa_cvq_map_buf(&s->vhost_vdpa, elem->out_sg, elem->out_num,
83
- vhost_vdpa_net_cvq_cmd_len(), iov[0].iov_base,
84
- &iov[0].iov_len, false);
85
- if (unlikely(!ok)) {
86
- return false;
87
+ assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
88
+
89
+ s = DO_UPCAST(VhostVDPAState, nc, nc);
90
+ if (!s->vhost_vdpa.shadow_vqs_enabled) {
91
+ return 0;
92
}
93
94
- iov[1].iov_base = s->cvq_cmd_in_buffer;
95
- ok = vhost_vdpa_cvq_map_buf(&s->vhost_vdpa, NULL, 0,
96
- sizeof(virtio_net_ctrl_ack), iov[1].iov_base,
97
- &in_copied, true);
98
- if (unlikely(!ok)) {
99
+ r = vhost_vdpa_cvq_map_buf(&s->vhost_vdpa, s->cvq_cmd_out_buffer,
100
+ vhost_vdpa_net_cvq_cmd_page_len(), false);
101
+ if (unlikely(r < 0)) {
102
+ return r;
103
+ }
104
+
105
+ r = vhost_vdpa_cvq_map_buf(&s->vhost_vdpa, s->cvq_cmd_in_buffer,
106
+ vhost_vdpa_net_cvq_cmd_page_len(), true);
107
+ if (unlikely(r < 0)) {
108
vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, s->cvq_cmd_out_buffer);
109
- return false;
110
}
111
112
- iov[1].iov_len = sizeof(virtio_net_ctrl_ack);
113
- return true;
114
+ return r;
115
+}
116
+
117
+static void vhost_vdpa_net_cvq_stop(NetClientState *nc)
118
+{
119
+ VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
120
+
121
+ assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
122
+
123
+ if (s->vhost_vdpa.shadow_vqs_enabled) {
124
+ vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, s->cvq_cmd_out_buffer);
125
+ vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, s->cvq_cmd_in_buffer);
126
+ }
127
}
128
129
static NetClientInfo net_vhost_vdpa_cvq_info = {
130
.type = NET_CLIENT_DRIVER_VHOST_VDPA,
131
.size = sizeof(VhostVDPAState),
132
.receive = vhost_vdpa_receive,
133
+ .start = vhost_vdpa_net_cvq_start,
134
+ .stop = vhost_vdpa_net_cvq_stop,
135
.cleanup = vhost_vdpa_cleanup,
136
.has_vnet_hdr = vhost_vdpa_has_vnet_hdr,
137
.has_ufo = vhost_vdpa_has_ufo,
138
@@ -XXX,XX +XXX,XX @@ static NetClientInfo net_vhost_vdpa_cvq_info = {
139
* Do not forward commands not supported by SVQ. Otherwise, the device could
140
* accept it and qemu would not know how to update the device model.
141
*/
142
-static bool vhost_vdpa_net_cvq_validate_cmd(const struct iovec *out,
143
- size_t out_num)
144
+static bool vhost_vdpa_net_cvq_validate_cmd(const void *out_buf, size_t len)
145
{
146
struct virtio_net_ctrl_hdr ctrl;
147
- size_t n;
148
149
- n = iov_to_buf(out, out_num, 0, &ctrl, sizeof(ctrl));
150
- if (unlikely(n < sizeof(ctrl))) {
151
+ if (unlikely(len < sizeof(ctrl))) {
152
qemu_log_mask(LOG_GUEST_ERROR,
153
- "%s: invalid legnth of out buffer %zu\n", __func__, n);
154
+ "%s: invalid legnth of out buffer %zu\n", __func__, len);
155
return false;
156
}
157
158
+ memcpy(&ctrl, out_buf, sizeof(ctrl));
159
switch (ctrl.class) {
160
case VIRTIO_NET_CTRL_MAC:
161
switch (ctrl.cmd) {
162
@@ -XXX,XX +XXX,XX @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq,
163
VhostVDPAState *s = opaque;
164
size_t in_len, dev_written;
165
virtio_net_ctrl_ack status = VIRTIO_NET_ERR;
166
- /* out and in buffers sent to the device */
167
- struct iovec dev_buffers[2] = {
168
- { .iov_base = s->cvq_cmd_out_buffer },
169
- { .iov_base = s->cvq_cmd_in_buffer },
170
+ /* Out buffer sent to both the vdpa device and the device model */
171
+ struct iovec out = {
172
+ .iov_base = s->cvq_cmd_out_buffer,
173
+ };
174
+ /* In buffer sent to the device */
175
+ const struct iovec dev_in = {
176
+ .iov_base = s->cvq_cmd_in_buffer,
177
+ .iov_len = sizeof(virtio_net_ctrl_ack),
178
};
179
/* in buffer used for device model */
180
const struct iovec in = {
181
@@ -XXX,XX +XXX,XX @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq,
182
int r = -EINVAL;
183
bool ok;
184
185
- ok = vhost_vdpa_net_cvq_map_elem(s, elem, dev_buffers);
186
- if (unlikely(!ok)) {
187
- goto out;
188
- }
30
-
189
-
31
-static void rtl8139_mmio_writel(void *opaque, hwaddr addr, uint32_t val)
190
- ok = vhost_vdpa_net_cvq_validate_cmd(&dev_buffers[0], 1);
32
-{
191
+ out.iov_len = iov_to_buf(elem->out_sg, elem->out_num, 0,
33
- rtl8139_io_writel(opaque, addr & 0xFF, val);
192
+ s->cvq_cmd_out_buffer,
34
-}
193
+ vhost_vdpa_net_cvq_cmd_len());
35
-
194
+ ok = vhost_vdpa_net_cvq_validate_cmd(s->cvq_cmd_out_buffer, out.iov_len);
36
-static uint32_t rtl8139_mmio_readb(void *opaque, hwaddr addr)
195
if (unlikely(!ok)) {
37
-{
196
goto out;
38
- return rtl8139_io_readb(opaque, addr & 0xFF);
197
}
39
-}
198
40
-
199
- r = vhost_svq_add(svq, &dev_buffers[0], 1, &dev_buffers[1], 1, elem);
41
-static uint32_t rtl8139_mmio_readw(void *opaque, hwaddr addr)
200
+ r = vhost_svq_add(svq, &out, 1, &dev_in, 1, elem);
42
-{
201
if (unlikely(r != 0)) {
43
- uint32_t val = rtl8139_io_readw(opaque, addr & 0xFF);
202
if (unlikely(r == -ENOSPC)) {
44
- return val;
203
qemu_log_mask(LOG_GUEST_ERROR, "%s: No space on device queue\n",
45
-}
204
@@ -XXX,XX +XXX,XX @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq,
46
-
205
goto out;
47
-static uint32_t rtl8139_mmio_readl(void *opaque, hwaddr addr)
206
}
48
-{
207
49
- uint32_t val = rtl8139_io_readl(opaque, addr & 0xFF);
208
- memcpy(&status, dev_buffers[1].iov_base, sizeof(status));
50
- return val;
209
+ memcpy(&status, s->cvq_cmd_in_buffer, sizeof(status));
51
-}
210
if (status != VIRTIO_NET_OK) {
52
-
211
goto out;
53
static int rtl8139_post_load(void *opaque, int version_id)
212
}
54
{
213
55
RTL8139State* s = opaque;
214
status = VIRTIO_NET_ERR;
56
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps rtl8139_io_ops = {
215
- virtio_net_handle_ctrl_iov(svq->vdev, &in, 1, dev_buffers, 1);
57
.endianness = DEVICE_LITTLE_ENDIAN,
216
+ virtio_net_handle_ctrl_iov(svq->vdev, &in, 1, &out, 1);
58
};
217
if (status != VIRTIO_NET_OK) {
59
218
error_report("Bad CVQ processing in model");
60
-static const MemoryRegionOps rtl8139_mmio_ops = {
219
}
61
- .old_mmio = {
220
@@ -XXX,XX +XXX,XX @@ out:
62
- .read = {
221
}
63
- rtl8139_mmio_readb,
222
vhost_svq_push_elem(svq, elem, MIN(in_len, sizeof(status)));
64
- rtl8139_mmio_readw,
223
g_free(elem);
65
- rtl8139_mmio_readl,
224
- if (dev_buffers[0].iov_base) {
66
- },
225
- vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, dev_buffers[0].iov_base);
67
- .write = {
226
- }
68
- rtl8139_mmio_writeb,
227
- if (dev_buffers[1].iov_base) {
69
- rtl8139_mmio_writew,
228
- vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, dev_buffers[1].iov_base);
70
- rtl8139_mmio_writel,
229
- }
71
- },
230
return r;
72
- },
231
}
73
- .endianness = DEVICE_LITTLE_ENDIAN,
74
-};
75
-
76
static void rtl8139_timer(void *opaque)
77
{
78
RTL8139State *s = opaque;
79
@@ -XXX,XX +XXX,XX @@ static void pci_rtl8139_realize(PCIDevice *dev, Error **errp)
80
81
memory_region_init_io(&s->bar_io, OBJECT(s), &rtl8139_io_ops, s,
82
"rtl8139", 0x100);
83
- memory_region_init_io(&s->bar_mem, OBJECT(s), &rtl8139_mmio_ops, s,
84
- "rtl8139", 0x100);
85
+ memory_region_init_alias(&s->bar_mem, OBJECT(s), "rtl8139-mem", &s->bar_io,
86
+ 0, 0x100);
87
+
88
pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->bar_io);
89
pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar_mem);
90
232
91
--
233
--
92
2.7.4
234
2.7.4
93
235
94
236
diff view generated by jsdifflib
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
1
From: Eugenio Pérez <eperezma@redhat.com>
2
2
3
Currently, net_socket_mcast_create(), net_socket_fd_init_dgram() and
3
So we can reuse it to inject state messages.
4
net_socket_fd_init() use the function such as fprintf(), perror() to
5
report an error message.
6
4
7
Now, convert these functions to Error.
5
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
6
Acked-by: Jason Wang <jasowang@redhat.com>
7
--
8
v7:
9
* Remove double free error
8
10
9
Cc: jasowang@redhat.com
11
v6:
10
Cc: armbru@redhat.com
12
* Do not assume in buffer sent to the device is sizeof(virtio_net_ctrl_ack)
11
Cc: berrange@redhat.com
13
12
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
14
v5:
13
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
15
* Do not use an artificial !NULL VirtQueueElement
14
Reviewed-by: Markus Armbruster <armbru@redhat.com>
16
* Use only out size instead of iovec dev_buffers for these functions.
17
15
Signed-off-by: Jason Wang <jasowang@redhat.com>
18
Signed-off-by: Jason Wang <jasowang@redhat.com>
16
---
19
---
17
net/socket.c | 82 ++++++++++++++++++++++++++++++++++++------------------------
20
net/vhost-vdpa.c | 59 ++++++++++++++++++++++++++++++++++++--------------------
18
1 file changed, 50 insertions(+), 32 deletions(-)
21
1 file changed, 38 insertions(+), 21 deletions(-)
19
22
20
diff --git a/net/socket.c b/net/socket.c
23
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
21
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
22
--- a/net/socket.c
25
--- a/net/vhost-vdpa.c
23
+++ b/net/socket.c
26
+++ b/net/vhost-vdpa.c
24
@@ -XXX,XX +XXX,XX @@ static void net_socket_send_dgram(void *opaque)
27
@@ -XXX,XX +XXX,XX @@ static void vhost_vdpa_net_cvq_stop(NetClientState *nc)
25
}
28
}
26
}
29
}
27
30
28
-static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr *localaddr)
31
+static ssize_t vhost_vdpa_net_cvq_add(VhostVDPAState *s, size_t out_len,
29
+static int net_socket_mcast_create(struct sockaddr_in *mcastaddr,
32
+ size_t in_len)
30
+ struct in_addr *localaddr,
33
+{
31
+ Error **errp)
34
+ /* Buffers for the device */
32
{
35
+ const struct iovec out = {
33
struct ip_mreq imr;
36
+ .iov_base = s->cvq_cmd_out_buffer,
34
int fd;
37
+ .iov_len = out_len,
35
@@ -XXX,XX +XXX,XX @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
38
+ };
36
#endif
39
+ const struct iovec in = {
37
40
+ .iov_base = s->cvq_cmd_in_buffer,
38
if (!IN_MULTICAST(ntohl(mcastaddr->sin_addr.s_addr))) {
41
+ .iov_len = sizeof(virtio_net_ctrl_ack),
39
- fprintf(stderr, "qemu: error: specified mcastaddr \"%s\" (0x%08x) "
42
+ };
40
- "does not contain a multicast address\n",
43
+ VhostShadowVirtqueue *svq = g_ptr_array_index(s->vhost_vdpa.shadow_vqs, 0);
41
- inet_ntoa(mcastaddr->sin_addr),
44
+ int r;
42
- (int)ntohl(mcastaddr->sin_addr.s_addr));
43
+ error_setg(errp, "specified mcastaddr %s (0x%08x) "
44
+ "does not contain a multicast address",
45
+ inet_ntoa(mcastaddr->sin_addr),
46
+ (int)ntohl(mcastaddr->sin_addr.s_addr));
47
return -1;
48
-
49
}
50
+
45
+
51
fd = qemu_socket(PF_INET, SOCK_DGRAM, 0);
46
+ r = vhost_svq_add(svq, &out, 1, &in, 1, NULL);
52
if (fd < 0) {
47
+ if (unlikely(r != 0)) {
53
- perror("socket(PF_INET, SOCK_DGRAM)");
48
+ if (unlikely(r == -ENOSPC)) {
54
+ error_setg_errno(errp, errno, "can't create datagram socket");
49
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: No space on device queue\n",
55
return -1;
50
+ __func__);
56
}
51
+ }
57
52
+ return r;
58
@@ -XXX,XX +XXX,XX @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
59
val = 1;
60
ret = qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
61
if (ret < 0) {
62
- perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
63
+ error_setg_errno(errp, errno,
64
+ "can't set socket option SO_REUSEADDR");
65
goto fail;
66
}
67
68
ret = bind(fd, (struct sockaddr *)mcastaddr, sizeof(*mcastaddr));
69
if (ret < 0) {
70
- perror("bind");
71
+ error_setg_errno(errp, errno, "can't bind ip=%s to socket",
72
+ inet_ntoa(mcastaddr->sin_addr));
73
goto fail;
74
}
75
76
@@ -XXX,XX +XXX,XX @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
77
ret = qemu_setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
78
&imr, sizeof(struct ip_mreq));
79
if (ret < 0) {
80
- perror("setsockopt(IP_ADD_MEMBERSHIP)");
81
+ error_setg_errno(errp, errno,
82
+ "can't add socket to multicast group %s",
83
+ inet_ntoa(imr.imr_multiaddr));
84
goto fail;
85
}
86
87
@@ -XXX,XX +XXX,XX @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
88
ret = qemu_setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP,
89
&loop, sizeof(loop));
90
if (ret < 0) {
91
- perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)");
92
+ error_setg_errno(errp, errno,
93
+ "can't force multicast message to loopback");
94
goto fail;
95
}
96
97
@@ -XXX,XX +XXX,XX @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
98
ret = qemu_setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
99
localaddr, sizeof(*localaddr));
100
if (ret < 0) {
101
- perror("setsockopt(IP_MULTICAST_IF)");
102
+ error_setg_errno(errp, errno,
103
+ "can't set the default network send interface");
104
goto fail;
105
}
106
}
107
@@ -XXX,XX +XXX,XX @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer,
108
const char *model,
109
const char *name,
110
int fd, int is_connected,
111
- const char *mcast)
112
+ const char *mcast,
113
+ Error **errp)
114
{
115
struct sockaddr_in saddr;
116
int newfd;
117
@@ -XXX,XX +XXX,XX @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer,
118
119
if (is_connected && mcast != NULL) {
120
if (parse_host_port(&saddr, mcast) < 0) {
121
- fprintf(stderr,
122
- "qemu: error: init_dgram: fd=%d failed parse_host_port()\n",
123
- fd);
124
+ error_setg(errp, "fd=%d failed parse_host_port()", fd);
125
goto err;
126
}
127
/* must be bound */
128
if (saddr.sin_addr.s_addr == 0) {
129
- fprintf(stderr, "qemu: error: init_dgram: fd=%d unbound, "
130
- "cannot setup multicast dst addr\n", fd);
131
+ error_setg(errp, "can't setup multicast destination address");
132
goto err;
133
}
134
/* clone dgram socket */
135
- newfd = net_socket_mcast_create(&saddr, NULL);
136
+ newfd = net_socket_mcast_create(&saddr, NULL, errp);
137
if (newfd < 0) {
138
- /* error already reported by net_socket_mcast_create() */
139
goto err;
140
}
141
/* clone newfd to fd, close newfd */
142
@@ -XXX,XX +XXX,XX @@ static NetSocketState *net_socket_fd_init_stream(NetClientState *peer,
143
144
static NetSocketState *net_socket_fd_init(NetClientState *peer,
145
const char *model, const char *name,
146
- int fd, int is_connected, const char *mc)
147
+ int fd, int is_connected,
148
+ const char *mc, Error **errp)
149
{
150
int so_type = -1, optlen=sizeof(so_type);
151
152
if(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type,
153
(socklen_t *)&optlen)< 0) {
154
- fprintf(stderr, "qemu: error: getsockopt(SO_TYPE) for fd=%d failed\n",
155
- fd);
156
+ error_setg(errp, "can't get socket option SO_TYPE");
157
closesocket(fd);
158
return NULL;
159
}
160
switch(so_type) {
161
case SOCK_DGRAM:
162
- return net_socket_fd_init_dgram(peer, model, name, fd, is_connected, mc);
163
+ return net_socket_fd_init_dgram(peer, model, name, fd, is_connected,
164
+ mc, errp);
165
case SOCK_STREAM:
166
return net_socket_fd_init_stream(peer, model, name, fd, is_connected);
167
default:
168
@@ -XXX,XX +XXX,XX @@ static int net_socket_connect_init(NetClientState *peer,
169
NetSocketState *s;
170
int fd, connected, ret;
171
struct sockaddr_in saddr;
172
+ Error *err = NULL;
173
174
if (parse_host_port(&saddr, host_str) < 0)
175
return -1;
176
@@ -XXX,XX +XXX,XX @@ static int net_socket_connect_init(NetClientState *peer,
177
break;
178
}
179
}
180
- s = net_socket_fd_init(peer, model, name, fd, connected, NULL);
181
- if (!s)
182
+ s = net_socket_fd_init(peer, model, name, fd, connected, NULL, &err);
183
+ if (!s) {
184
+ error_report_err(err);
185
return -1;
186
+ }
53
+ }
187
+
54
+
188
snprintf(s->nc.info_str, sizeof(s->nc.info_str),
55
+ /*
189
"socket: connect to %s:%d",
56
+ * We can poll here since we've had BQL from the time we sent the
190
inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
57
+ * descriptor. Also, we need to take the answer before SVQ pulls by itself,
191
@@ -XXX,XX +XXX,XX @@ static int net_socket_mcast_init(NetClientState *peer,
58
+ * when BQL is released
192
int fd;
59
+ */
193
struct sockaddr_in saddr;
60
+ return vhost_svq_poll(svq);
194
struct in_addr localaddr, *param_localaddr;
61
+}
195
+ Error *err = NULL;
62
+
196
63
static NetClientInfo net_vhost_vdpa_cvq_info = {
197
if (parse_host_port(&saddr, host_str) < 0)
64
.type = NET_CLIENT_DRIVER_VHOST_VDPA,
198
return -1;
65
.size = sizeof(VhostVDPAState),
199
@@ -XXX,XX +XXX,XX @@ static int net_socket_mcast_init(NetClientState *peer,
66
@@ -XXX,XX +XXX,XX @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq,
200
param_localaddr = NULL;
67
void *opaque)
68
{
69
VhostVDPAState *s = opaque;
70
- size_t in_len, dev_written;
71
+ size_t in_len;
72
virtio_net_ctrl_ack status = VIRTIO_NET_ERR;
73
/* Out buffer sent to both the vdpa device and the device model */
74
struct iovec out = {
75
.iov_base = s->cvq_cmd_out_buffer,
76
};
77
- /* In buffer sent to the device */
78
- const struct iovec dev_in = {
79
- .iov_base = s->cvq_cmd_in_buffer,
80
- .iov_len = sizeof(virtio_net_ctrl_ack),
81
- };
82
/* in buffer used for device model */
83
const struct iovec in = {
84
.iov_base = &status,
85
.iov_len = sizeof(status),
86
};
87
- int r = -EINVAL;
88
+ ssize_t dev_written = -EINVAL;
89
bool ok;
90
91
out.iov_len = iov_to_buf(elem->out_sg, elem->out_num, 0,
92
@@ -XXX,XX +XXX,XX @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq,
93
goto out;
201
}
94
}
202
95
203
- fd = net_socket_mcast_create(&saddr, param_localaddr);
96
- r = vhost_svq_add(svq, &out, 1, &dev_in, 1, elem);
204
- if (fd < 0)
97
- if (unlikely(r != 0)) {
205
+ fd = net_socket_mcast_create(&saddr, param_localaddr, &err);
98
- if (unlikely(r == -ENOSPC)) {
206
+ if (fd < 0) {
99
- qemu_log_mask(LOG_GUEST_ERROR, "%s: No space on device queue\n",
207
+ error_report_err(err);
100
- __func__);
208
return -1;
101
- }
209
+ }
102
+ dev_written = vhost_vdpa_net_cvq_add(s, out.iov_len, sizeof(status));
210
103
+ if (unlikely(dev_written < 0)) {
211
- s = net_socket_fd_init(peer, model, name, fd, 0, NULL);
104
goto out;
212
- if (!s)
213
+ s = net_socket_fd_init(peer, model, name, fd, 0, NULL, &err);
214
+ if (!s) {
215
+ error_report_err(err);
216
return -1;
217
+ }
218
219
s->dgram_dst = saddr;
220
221
@@ -XXX,XX +XXX,XX @@ static int net_socket_udp_init(NetClientState *peer,
222
NetSocketState *s;
223
int fd, ret;
224
struct sockaddr_in laddr, raddr;
225
+ Error *err = NULL;
226
227
if (parse_host_port(&laddr, lhost) < 0) {
228
return -1;
229
@@ -XXX,XX +XXX,XX @@ static int net_socket_udp_init(NetClientState *peer,
230
}
105
}
231
qemu_set_nonblock(fd);
106
232
107
- /*
233
- s = net_socket_fd_init(peer, model, name, fd, 0, NULL);
108
- * We can poll here since we've had BQL from the time we sent the
234
+ s = net_socket_fd_init(peer, model, name, fd, 0, NULL, &err);
109
- * descriptor. Also, we need to take the answer before SVQ pulls by itself,
235
if (!s) {
110
- * when BQL is released
236
+ error_report_err(err);
111
- */
237
return -1;
112
- dev_written = vhost_svq_poll(svq);
113
if (unlikely(dev_written < sizeof(status))) {
114
error_report("Insufficient written data (%zu)", dev_written);
115
goto out;
116
@@ -XXX,XX +XXX,XX @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq,
117
118
memcpy(&status, s->cvq_cmd_in_buffer, sizeof(status));
119
if (status != VIRTIO_NET_OK) {
120
- goto out;
121
+ return VIRTIO_NET_ERR;
238
}
122
}
239
123
240
@@ -XXX,XX +XXX,XX @@ int net_init_socket(const Netdev *netdev, const char *name,
124
status = VIRTIO_NET_ERR;
241
return -1;
125
@@ -XXX,XX +XXX,XX @@ out:
242
}
126
}
243
qemu_set_nonblock(fd);
127
vhost_svq_push_elem(svq, elem, MIN(in_len, sizeof(status)));
244
- if (!net_socket_fd_init(peer, "socket", name, fd, 1, sock->mcast)) {
128
g_free(elem);
245
+ if (!net_socket_fd_init(peer, "socket", name, fd, 1, sock->mcast,
129
- return r;
246
+ errp)) {
130
+ return dev_written < 0 ? dev_written : 0;
247
return -1;
131
}
248
}
132
249
return 0;
133
static const VhostShadowVirtqueueOps vhost_vdpa_net_svq_ops = {
250
--
134
--
251
2.7.4
135
2.7.4
252
136
253
137
diff view generated by jsdifflib
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
1
From: Eugenio Pérez <eperezma@redhat.com>
2
2
3
When -net socket fails, it first reports a specific error, then
3
It allows per-net client operations right after device's successful
4
a generic one, like this:
4
start. In particular, to load the device status.
5
5
6
$ ./x86_64-softmmu/qemu-system-x86_64 -net socket,mcast=230.0.0.1:1234,listen
6
Vhost-vdpa net will use it to add the CVQ buffers to restore the device
7
qemu-system-x86_64: -net socket,mcast=230.0.0.1:1234,listen: exactly one of listen=, connect=, mcast= or udp= is required
7
status.
8
qemu-system-x86_64: -net socket,mcast=230.0.0.1:1234,listen: Device 'socket' could not be initialized
9
8
10
Convert net_socket_*_init() to Error to get rid of the superfluous second
9
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
11
error message. After the patch, the effect like this:
10
Acked-by: Jason Wang <jasowang@redhat.com>
12
13
$ ./x86_64-softmmu/qemu-system-x86_64 -net socket,mcast=230.0.0.1:1234,listen
14
qemu-system-x86_64: -net socket,mcast=230.0.0.1:1234,listen: exactly one of listen=, connect=, mcast= or udp= is requireda
15
16
This also fixes a few silent failures to report an error.
17
18
Cc: jasowang@redhat.com
19
Cc: armbru@redhat.com
20
Cc: berrange@redhat.com
21
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
22
Reviewed-by: Markus Armbruster <armbru@redhat.com>
23
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
24
---
12
---
25
net/socket.c | 92 +++++++++++++++++++++++++++++-------------------------------
13
hw/net/vhost_net.c | 7 +++++++
26
1 file changed, 44 insertions(+), 48 deletions(-)
14
include/net/net.h | 2 ++
15
2 files changed, 9 insertions(+)
27
16
28
diff --git a/net/socket.c b/net/socket.c
17
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
29
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
30
--- a/net/socket.c
19
--- a/hw/net/vhost_net.c
31
+++ b/net/socket.c
20
+++ b/hw/net/vhost_net.c
32
@@ -XXX,XX +XXX,XX @@ static void net_socket_accept(void *opaque)
21
@@ -XXX,XX +XXX,XX @@ static int vhost_net_start_one(struct vhost_net *net,
33
static int net_socket_listen_init(NetClientState *peer,
34
const char *model,
35
const char *name,
36
- const char *host_str)
37
+ const char *host_str,
38
+ Error **errp)
39
{
40
NetClientState *nc;
41
NetSocketState *s;
42
struct sockaddr_in saddr;
43
int fd, ret;
44
- Error *err = NULL;
45
46
- if (parse_host_port(&saddr, host_str, &err) < 0) {
47
- error_report_err(err);
48
+ if (parse_host_port(&saddr, host_str, errp) < 0) {
49
return -1;
50
}
51
52
fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
53
if (fd < 0) {
54
- perror("socket");
55
+ error_setg_errno(errp, errno, "can't create stream socket");
56
return -1;
57
}
58
qemu_set_nonblock(fd);
59
@@ -XXX,XX +XXX,XX @@ static int net_socket_listen_init(NetClientState *peer,
60
61
ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
62
if (ret < 0) {
63
- perror("bind");
64
+ error_setg_errno(errp, errno, "can't bind ip=%s to socket",
65
+ inet_ntoa(saddr.sin_addr));
66
closesocket(fd);
67
return -1;
68
}
69
ret = listen(fd, 0);
70
if (ret < 0) {
71
- perror("listen");
72
+ error_setg_errno(errp, errno, "can't listen on socket");
73
closesocket(fd);
74
return -1;
75
}
76
@@ -XXX,XX +XXX,XX @@ static int net_socket_listen_init(NetClientState *peer,
77
static int net_socket_connect_init(NetClientState *peer,
78
const char *model,
79
const char *name,
80
- const char *host_str)
81
+ const char *host_str,
82
+ Error **errp)
83
{
84
NetSocketState *s;
85
int fd, connected, ret;
86
struct sockaddr_in saddr;
87
- Error *err = NULL;
88
89
- if (parse_host_port(&saddr, host_str, &err) < 0) {
90
- error_report_err(err);
91
+ if (parse_host_port(&saddr, host_str, errp) < 0) {
92
return -1;
93
}
94
95
fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
96
if (fd < 0) {
97
- perror("socket");
98
+ error_setg_errno(errp, errno, "can't create stream socket");
99
return -1;
100
}
101
qemu_set_nonblock(fd);
102
@@ -XXX,XX +XXX,XX @@ static int net_socket_connect_init(NetClientState *peer,
103
errno == EINVAL) {
104
break;
105
} else {
106
- perror("connect");
107
+ error_setg_errno(errp, errno, "can't connect socket");
108
closesocket(fd);
109
return -1;
110
}
22
}
111
@@ -XXX,XX +XXX,XX @@ static int net_socket_connect_init(NetClientState *peer,
112
break;
113
}
23
}
114
}
24
}
115
- s = net_socket_fd_init(peer, model, name, fd, connected, NULL, &err);
25
+
116
+ s = net_socket_fd_init(peer, model, name, fd, connected, NULL, errp);
26
+ if (net->nc->info->load) {
117
if (!s) {
27
+ r = net->nc->info->load(net->nc);
118
- error_report_err(err);
28
+ if (r < 0) {
119
return -1;
29
+ goto fail;
120
}
121
122
@@ -XXX,XX +XXX,XX @@ static int net_socket_mcast_init(NetClientState *peer,
123
const char *model,
124
const char *name,
125
const char *host_str,
126
- const char *localaddr_str)
127
+ const char *localaddr_str,
128
+ Error **errp)
129
{
130
NetSocketState *s;
131
int fd;
132
struct sockaddr_in saddr;
133
struct in_addr localaddr, *param_localaddr;
134
- Error *err = NULL;
135
136
- if (parse_host_port(&saddr, host_str, &err) < 0) {
137
- error_report_err(err);
138
+ if (parse_host_port(&saddr, host_str, errp) < 0) {
139
return -1;
140
}
141
142
if (localaddr_str != NULL) {
143
- if (inet_aton(localaddr_str, &localaddr) == 0)
144
+ if (inet_aton(localaddr_str, &localaddr) == 0) {
145
+ error_setg(errp, "localaddr '%s' is not a valid IPv4 address",
146
+ localaddr_str);
147
return -1;
148
+ }
30
+ }
149
param_localaddr = &localaddr;
31
+ }
150
} else {
151
param_localaddr = NULL;
152
}
153
154
- fd = net_socket_mcast_create(&saddr, param_localaddr, &err);
155
+ fd = net_socket_mcast_create(&saddr, param_localaddr, errp);
156
if (fd < 0) {
157
- error_report_err(err);
158
return -1;
159
}
160
161
- s = net_socket_fd_init(peer, model, name, fd, 0, NULL, &err);
162
+ s = net_socket_fd_init(peer, model, name, fd, 0, NULL, errp);
163
if (!s) {
164
- error_report_err(err);
165
return -1;
166
}
167
168
@@ -XXX,XX +XXX,XX @@ static int net_socket_udp_init(NetClientState *peer,
169
const char *model,
170
const char *name,
171
const char *rhost,
172
- const char *lhost)
173
+ const char *lhost,
174
+ Error **errp)
175
{
176
NetSocketState *s;
177
int fd, ret;
178
struct sockaddr_in laddr, raddr;
179
- Error *err = NULL;
180
181
- if (parse_host_port(&laddr, lhost, &err) < 0) {
182
- error_report_err(err);
183
+ if (parse_host_port(&laddr, lhost, errp) < 0) {
184
return -1;
185
}
186
187
- if (parse_host_port(&raddr, rhost, &err) < 0) {
188
- error_report_err(err);
189
+ if (parse_host_port(&raddr, rhost, errp) < 0) {
190
return -1;
191
}
192
193
fd = qemu_socket(PF_INET, SOCK_DGRAM, 0);
194
if (fd < 0) {
195
- perror("socket(PF_INET, SOCK_DGRAM)");
196
+ error_setg_errno(errp, errno, "can't create datagram socket");
197
return -1;
198
}
199
200
ret = socket_set_fast_reuse(fd);
201
if (ret < 0) {
202
+ error_setg_errno(errp, errno,
203
+ "can't set socket option SO_REUSEADDR");
204
closesocket(fd);
205
return -1;
206
}
207
ret = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr));
208
if (ret < 0) {
209
- perror("bind");
210
+ error_setg_errno(errp, errno, "can't bind ip=%s to socket",
211
+ inet_ntoa(laddr.sin_addr));
212
closesocket(fd);
213
return -1;
214
}
215
qemu_set_nonblock(fd);
216
217
- s = net_socket_fd_init(peer, model, name, fd, 0, NULL, &err);
218
+ s = net_socket_fd_init(peer, model, name, fd, 0, NULL, errp);
219
if (!s) {
220
- error_report_err(err);
221
return -1;
222
}
223
224
@@ -XXX,XX +XXX,XX @@ static int net_socket_udp_init(NetClientState *peer,
225
int net_init_socket(const Netdev *netdev, const char *name,
226
NetClientState *peer, Error **errp)
227
{
228
- /* FIXME error_setg(errp, ...) on failure */
229
- Error *err = NULL;
230
const NetdevSocketOptions *sock;
231
232
assert(netdev->type == NET_CLIENT_DRIVER_SOCKET);
233
@@ -XXX,XX +XXX,XX @@ int net_init_socket(const Netdev *netdev, const char *name,
234
235
if (sock->has_listen + sock->has_connect + sock->has_mcast +
236
sock->has_udp > 1) {
237
- error_report("exactly one of listen=, connect=, mcast= or udp="
238
- " is required");
239
+ error_setg(errp, "exactly one of listen=, connect=, mcast= or udp="
240
+ " is required");
241
return -1;
242
}
243
244
if (sock->has_localaddr && !sock->has_mcast && !sock->has_udp) {
245
- error_report("localaddr= is only valid with mcast= or udp=");
246
+ error_setg(errp, "localaddr= is only valid with mcast= or udp=");
247
return -1;
248
}
249
250
if (sock->has_fd) {
251
int fd;
252
253
- fd = monitor_fd_param(cur_mon, sock->fd, &err);
254
+ fd = monitor_fd_param(cur_mon, sock->fd, errp);
255
if (fd == -1) {
256
- error_report_err(err);
257
return -1;
258
}
259
qemu_set_nonblock(fd);
260
@@ -XXX,XX +XXX,XX @@ int net_init_socket(const Netdev *netdev, const char *name,
261
}
262
263
if (sock->has_listen) {
264
- if (net_socket_listen_init(peer, "socket", name, sock->listen) == -1) {
265
+ if (net_socket_listen_init(peer, "socket", name, sock->listen, errp)
266
+ < 0) {
267
return -1;
268
}
269
return 0;
270
}
271
272
if (sock->has_connect) {
273
- if (net_socket_connect_init(peer, "socket", name, sock->connect) ==
274
- -1) {
275
+ if (net_socket_connect_init(peer, "socket", name, sock->connect, errp)
276
+ < 0) {
277
return -1;
278
}
279
return 0;
280
@@ -XXX,XX +XXX,XX @@ int net_init_socket(const Netdev *netdev, const char *name,
281
/* if sock->localaddr is missing, it has been initialized to "all bits
282
* zero" */
283
if (net_socket_mcast_init(peer, "socket", name, sock->mcast,
284
- sock->localaddr) == -1) {
285
+ sock->localaddr, errp) < 0) {
286
return -1;
287
}
288
return 0;
289
@@ -XXX,XX +XXX,XX @@ int net_init_socket(const Netdev *netdev, const char *name,
290
291
assert(sock->has_udp);
292
if (!sock->has_localaddr) {
293
- error_report("localaddr= is mandatory with udp=");
294
+ error_setg(errp, "localaddr= is mandatory with udp=");
295
return -1;
296
}
297
- if (net_socket_udp_init(peer, "socket", name, sock->udp, sock->localaddr) ==
298
- -1) {
299
+ if (net_socket_udp_init(peer, "socket", name, sock->udp, sock->localaddr,
300
+ errp) < 0) {
301
return -1;
302
}
303
return 0;
32
return 0;
33
fail:
34
file.fd = -1;
35
diff --git a/include/net/net.h b/include/net/net.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/include/net/net.h
38
+++ b/include/net/net.h
39
@@ -XXX,XX +XXX,XX @@ typedef struct NICConf {
40
typedef void (NetPoll)(NetClientState *, bool enable);
41
typedef bool (NetCanReceive)(NetClientState *);
42
typedef int (NetStart)(NetClientState *);
43
+typedef int (NetLoad)(NetClientState *);
44
typedef void (NetStop)(NetClientState *);
45
typedef ssize_t (NetReceive)(NetClientState *, const uint8_t *, size_t);
46
typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int);
47
@@ -XXX,XX +XXX,XX @@ typedef struct NetClientInfo {
48
NetReceiveIOV *receive_iov;
49
NetCanReceive *can_receive;
50
NetStart *start;
51
+ NetLoad *load;
52
NetStop *stop;
53
NetCleanup *cleanup;
54
LinkStatusChanged *link_status_changed;
304
--
55
--
305
2.7.4
56
2.7.4
306
57
307
58
diff view generated by jsdifflib
1
From: Wang Yong <wang.yong155@zte.com.cn>
1
From: Eugenio Pérez <eperezma@redhat.com>
2
2
3
IOThread uses AioContext event loop and does not run a GMainContext.
3
This is needed so the destination vdpa device see the same state a the
4
Therefore,chardev cannot work in IOThread,such as the chardev is
4
guest set in the source.
5
used for colo-compare packets reception.
6
5
7
This patch makes the IOThread run the GMainContext event loop,
6
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
8
chardev and IOThread can work together.
7
Acked-by: Jason Wang <jasowang@redhat.com>
9
10
Reviewed-by: Fam Zheng <famz@redhat.com>
11
Signed-off-by: Wang Yong <wang.yong155@zte.com.cn>
12
Signed-off-by: Wang Guang <wang.guang55@zte.com.cn>
13
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
14
---
9
---
15
include/sysemu/iothread.h | 4 ++++
10
net/vhost-vdpa.c | 40 ++++++++++++++++++++++++++++++++++++++++
16
iothread.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
11
1 file changed, 40 insertions(+)
17
2 files changed, 49 insertions(+)
18
12
19
diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h
13
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
20
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
21
--- a/include/sysemu/iothread.h
15
--- a/net/vhost-vdpa.c
22
+++ b/include/sysemu/iothread.h
16
+++ b/net/vhost-vdpa.c
23
@@ -XXX,XX +XXX,XX @@ typedef struct {
17
@@ -XXX,XX +XXX,XX @@ static ssize_t vhost_vdpa_net_cvq_add(VhostVDPAState *s, size_t out_len,
24
18
return vhost_svq_poll(svq);
25
QemuThread thread;
19
}
26
AioContext *ctx;
20
27
+ GMainContext *worker_context;
21
+static int vhost_vdpa_net_load(NetClientState *nc)
28
+ GMainLoop *main_loop;
22
+{
29
+ GOnce once;
23
+ VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
30
QemuMutex init_done_lock;
24
+ const struct vhost_vdpa *v = &s->vhost_vdpa;
31
QemuCond init_done_cond; /* is thread initialization done? */
25
+ const VirtIONet *n;
32
bool stopping;
26
+ uint64_t features;
33
@@ -XXX,XX +XXX,XX @@ typedef struct {
34
char *iothread_get_id(IOThread *iothread);
35
AioContext *iothread_get_aio_context(IOThread *iothread);
36
void iothread_stop_all(void);
37
+GMainContext *iothread_get_g_main_context(IOThread *iothread);
38
39
#endif /* IOTHREAD_H */
40
diff --git a/iothread.c b/iothread.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/iothread.c
43
+++ b/iothread.c
44
@@ -XXX,XX +XXX,XX @@ static void *iothread_run(void *opaque)
45
46
while (!atomic_read(&iothread->stopping)) {
47
aio_poll(iothread->ctx, true);
48
+
27
+
49
+ if (atomic_read(&iothread->worker_context)) {
28
+ assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
50
+ GMainLoop *loop;
51
+
29
+
52
+ g_main_context_push_thread_default(iothread->worker_context);
30
+ if (!v->shadow_vqs_enabled) {
53
+ iothread->main_loop =
31
+ return 0;
54
+ g_main_loop_new(iothread->worker_context, TRUE);
32
+ }
55
+ loop = iothread->main_loop;
56
+
33
+
57
+ g_main_loop_run(iothread->main_loop);
34
+ n = VIRTIO_NET(v->dev->vdev);
58
+ iothread->main_loop = NULL;
35
+ features = n->parent_obj.guest_features;
59
+ g_main_loop_unref(loop);
36
+ if (features & BIT_ULL(VIRTIO_NET_F_CTRL_MAC_ADDR)) {
37
+ const struct virtio_net_ctrl_hdr ctrl = {
38
+ .class = VIRTIO_NET_CTRL_MAC,
39
+ .cmd = VIRTIO_NET_CTRL_MAC_ADDR_SET,
40
+ };
41
+ char *cursor = s->cvq_cmd_out_buffer;
42
+ ssize_t dev_written;
60
+
43
+
61
+ g_main_context_pop_thread_default(iothread->worker_context);
44
+ memcpy(cursor, &ctrl, sizeof(ctrl));
62
+ g_main_context_unref(iothread->worker_context);
45
+ cursor += sizeof(ctrl);
63
+ iothread->worker_context = NULL;
46
+ memcpy(cursor, n->mac, sizeof(n->mac));
47
+
48
+ dev_written = vhost_vdpa_net_cvq_add(s, sizeof(ctrl) + sizeof(n->mac),
49
+ sizeof(virtio_net_ctrl_ack));
50
+ if (unlikely(dev_written < 0)) {
51
+ return dev_written;
64
+ }
52
+ }
65
}
53
+
66
54
+ return *((virtio_net_ctrl_ack *)s->cvq_cmd_in_buffer) != VIRTIO_NET_OK;
67
rcu_unregister_thread();
68
@@ -XXX,XX +XXX,XX @@ static int iothread_stop(Object *object, void *opaque)
69
}
70
iothread->stopping = true;
71
aio_notify(iothread->ctx);
72
+ if (atomic_read(&iothread->main_loop)) {
73
+ g_main_loop_quit(iothread->main_loop);
74
+ }
55
+ }
75
qemu_thread_join(&iothread->thread);
76
return 0;
77
}
78
@@ -XXX,XX +XXX,XX @@ static void iothread_complete(UserCreatable *obj, Error **errp)
79
80
qemu_mutex_init(&iothread->init_done_lock);
81
qemu_cond_init(&iothread->init_done_cond);
82
+ iothread->once = (GOnce) G_ONCE_INIT;
83
84
/* This assumes we are called from a thread with useful CPU affinity for us
85
* to inherit.
86
@@ -XXX,XX +XXX,XX @@ void iothread_stop_all(void)
87
88
object_child_foreach(container, iothread_stop, NULL);
89
}
90
+
56
+
91
+static gpointer iothread_g_main_context_init(gpointer opaque)
57
+ return 0;
92
+{
93
+ AioContext *ctx;
94
+ IOThread *iothread = opaque;
95
+ GSource *source;
96
+
97
+ iothread->worker_context = g_main_context_new();
98
+
99
+ ctx = iothread_get_aio_context(iothread);
100
+ source = aio_get_g_source(ctx);
101
+ g_source_attach(source, iothread->worker_context);
102
+ g_source_unref(source);
103
+
104
+ aio_notify(iothread->ctx);
105
+ return NULL;
106
+}
58
+}
107
+
59
+
108
+GMainContext *iothread_get_g_main_context(IOThread *iothread)
60
static NetClientInfo net_vhost_vdpa_cvq_info = {
109
+{
61
.type = NET_CLIENT_DRIVER_VHOST_VDPA,
110
+ g_once(&iothread->once, iothread_g_main_context_init, iothread);
62
.size = sizeof(VhostVDPAState),
111
+
63
.receive = vhost_vdpa_receive,
112
+ return iothread->worker_context;
64
.start = vhost_vdpa_net_cvq_start,
113
+}
65
+ .load = vhost_vdpa_net_load,
66
.stop = vhost_vdpa_net_cvq_stop,
67
.cleanup = vhost_vdpa_cleanup,
68
.has_vnet_hdr = vhost_vdpa_has_vnet_hdr,
114
--
69
--
115
2.7.4
70
2.7.4
116
71
117
72
diff view generated by jsdifflib
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
1
From: Eugenio Pérez <eperezma@redhat.com>
2
2
3
Cc: jasowang@redhat.com
3
We can restore the device state in the destination via CVQ now. Remove
4
Cc: jiri@resnulli.us
4
the migration blocker.
5
Cc: armbru@redhat.com
5
6
Cc: f4bug@amsat.org
6
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
7
Suggested-by: Markus Armbruster <armbru@redhat.com>
7
Acked-by: Jason Wang <jasowang@redhat.com>
8
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
9
Reviewed-by: Markus Armbruster <armbru@redhat.com>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
9
---
13
hw/net/rocker/rocker.c | 18 +++++++++---------
10
hw/virtio/vhost-vdpa.c | 15 ---------------
14
1 file changed, 9 insertions(+), 9 deletions(-)
11
include/hw/virtio/vhost-vdpa.h | 1 -
12
net/vhost-vdpa.c | 2 --
13
3 files changed, 18 deletions(-)
15
14
16
diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c
15
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/net/rocker/rocker.c
17
--- a/hw/virtio/vhost-vdpa.c
19
+++ b/hw/net/rocker/rocker.c
18
+++ b/hw/virtio/vhost-vdpa.c
20
@@ -XXX,XX +XXX,XX @@ struct rocker {
19
@@ -XXX,XX +XXX,XX @@ static bool vhost_vdpa_svqs_start(struct vhost_dev *dev)
21
QLIST_ENTRY(rocker) next;
20
return true;
22
};
23
24
-#define ROCKER "rocker"
25
+#define TYPE_ROCKER "rocker"
26
27
-#define to_rocker(obj) \
28
- OBJECT_CHECK(Rocker, (obj), ROCKER)
29
+#define ROCKER(obj) \
30
+ OBJECT_CHECK(Rocker, (obj), TYPE_ROCKER)
31
32
static QLIST_HEAD(, rocker) rockers;
33
34
@@ -XXX,XX +XXX,XX @@ static World *rocker_world_type_by_name(Rocker *r, const char *name)
35
36
static void pci_rocker_realize(PCIDevice *dev, Error **errp)
37
{
38
- Rocker *r = to_rocker(dev);
39
+ Rocker *r = ROCKER(dev);
40
const MACAddr zero = { .a = { 0, 0, 0, 0, 0, 0 } };
41
const MACAddr dflt = { .a = { 0x52, 0x54, 0x00, 0x12, 0x35, 0x01 } };
42
static int sw_index;
43
@@ -XXX,XX +XXX,XX @@ static void pci_rocker_realize(PCIDevice *dev, Error **errp)
44
/* validate switch properties */
45
46
if (!r->name) {
47
- r->name = g_strdup(ROCKER);
48
+ r->name = g_strdup(TYPE_ROCKER);
49
}
21
}
50
22
51
if (rocker_find(r->name)) {
23
- if (v->migration_blocker) {
52
@@ -XXX,XX +XXX,XX @@ err_world_type_by_name:
24
- int r = migrate_add_blocker(v->migration_blocker, &err);
53
25
- if (unlikely(r < 0)) {
54
static void pci_rocker_uninit(PCIDevice *dev)
26
- return false;
55
{
27
- }
56
- Rocker *r = to_rocker(dev);
28
- }
57
+ Rocker *r = ROCKER(dev);
29
-
58
int i;
30
for (i = 0; i < v->shadow_vqs->len; ++i) {
59
31
VirtQueue *vq = virtio_get_queue(dev->vdev, dev->vq_index + i);
60
QLIST_REMOVE(r, next);
32
VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i);
61
@@ -XXX,XX +XXX,XX @@ static void pci_rocker_uninit(PCIDevice *dev)
33
@@ -XXX,XX +XXX,XX @@ err:
62
34
vhost_svq_stop(svq);
63
static void rocker_reset(DeviceState *dev)
35
}
64
{
36
65
- Rocker *r = to_rocker(dev);
37
- if (v->migration_blocker) {
66
+ Rocker *r = ROCKER(dev);
38
- migrate_del_blocker(v->migration_blocker);
67
int i;
39
- }
68
40
-
69
for (i = 0; i < ROCKER_WORLD_TYPE_MAX; i++) {
41
return false;
70
@@ -XXX,XX +XXX,XX @@ static Property rocker_properties[] = {
71
};
72
73
static const VMStateDescription rocker_vmsd = {
74
- .name = ROCKER,
75
+ .name = TYPE_ROCKER,
76
.unmigratable = 1,
77
};
78
79
@@ -XXX,XX +XXX,XX @@ static void rocker_class_init(ObjectClass *klass, void *data)
80
}
42
}
81
43
82
static const TypeInfo rocker_info = {
44
@@ -XXX,XX +XXX,XX @@ static void vhost_vdpa_svqs_stop(struct vhost_dev *dev)
83
- .name = ROCKER,
45
VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i);
84
+ .name = TYPE_ROCKER,
46
vhost_vdpa_svq_unmap_rings(dev, svq);
85
.parent = TYPE_PCI_DEVICE,
47
}
86
.instance_size = sizeof(Rocker),
48
-
87
.class_init = rocker_class_init,
49
- if (v->migration_blocker) {
50
- migrate_del_blocker(v->migration_blocker);
51
- }
52
}
53
54
static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started)
55
diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h
56
index XXXXXXX..XXXXXXX 100644
57
--- a/include/hw/virtio/vhost-vdpa.h
58
+++ b/include/hw/virtio/vhost-vdpa.h
59
@@ -XXX,XX +XXX,XX @@ typedef struct vhost_vdpa {
60
bool shadow_vqs_enabled;
61
/* IOVA mapping used by the Shadow Virtqueue */
62
VhostIOVATree *iova_tree;
63
- Error *migration_blocker;
64
GPtrArray *shadow_vqs;
65
const VhostShadowVirtqueueOps *shadow_vq_ops;
66
void *shadow_vq_ops_opaque;
67
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/net/vhost-vdpa.c
70
+++ b/net/vhost-vdpa.c
71
@@ -XXX,XX +XXX,XX @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer,
72
73
s->vhost_vdpa.shadow_vq_ops = &vhost_vdpa_net_svq_ops;
74
s->vhost_vdpa.shadow_vq_ops_opaque = s;
75
- error_setg(&s->vhost_vdpa.migration_blocker,
76
- "Migration disabled: vhost-vdpa uses CVQ.");
77
}
78
ret = vhost_vdpa_add(nc, (void *)&s->vhost_vdpa, queue_pair_index, nvqs);
79
if (ret) {
88
--
80
--
89
2.7.4
81
2.7.4
90
82
91
83
diff view generated by jsdifflib
New patch
1
From: Zhang Chen <chen.zhang@intel.com>
1
2
3
When enabled the virtio-net-pci, guest network packet will
4
load the vnet_hdr. In COLO status, the primary VM's network
5
packet maybe redirect to another VM, it needs filter-redirect
6
enable the vnet_hdr flag at the same time, COLO-proxy will
7
correctly parse the original network packet. If have any
8
misconfiguration here, the vnet_hdr_len is wrong for parse
9
the packet, the data+offset will point to wrong place.
10
11
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
---
14
net/colo.c | 25 ++++++++++++++++---------
15
net/colo.h | 1 +
16
net/trace-events | 2 +-
17
3 files changed, 18 insertions(+), 10 deletions(-)
18
19
diff --git a/net/colo.c b/net/colo.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/net/colo.c
22
+++ b/net/colo.c
23
@@ -XXX,XX +XXX,XX @@ int parse_packet_early(Packet *pkt)
24
{
25
int network_length;
26
static const uint8_t vlan[] = {0x81, 0x00};
27
- uint8_t *data = pkt->data + pkt->vnet_hdr_len;
28
+ uint8_t *data = pkt->data;
29
uint16_t l3_proto;
30
ssize_t l2hdr_len;
31
32
- if (data == NULL) {
33
- trace_colo_proxy_main_vnet_info("This packet is not parsed correctly, "
34
- "pkt->vnet_hdr_len", pkt->vnet_hdr_len);
35
+ assert(data);
36
+
37
+ /* Check the received vnet_hdr_len then add the offset */
38
+ if ((pkt->vnet_hdr_len > sizeof(struct virtio_net_hdr_v1_hash)) ||
39
+ (pkt->size < sizeof(struct eth_header) + sizeof(struct vlan_header) +
40
+ pkt->vnet_hdr_len)) {
41
+ /*
42
+ * The received remote packet maybe misconfiguration here,
43
+ * Please enable/disable filter module's the vnet_hdr flag at
44
+ * the same time.
45
+ */
46
+ trace_colo_proxy_main_vnet_info("This received packet load wrong ",
47
+ pkt->vnet_hdr_len, pkt->size);
48
return 1;
49
}
50
- l2hdr_len = eth_get_l2_hdr_length(data);
51
+ data += pkt->vnet_hdr_len;
52
53
- if (pkt->size < ETH_HLEN + pkt->vnet_hdr_len) {
54
- trace_colo_proxy_main("pkt->size < ETH_HLEN");
55
- return 1;
56
- }
57
+ l2hdr_len = eth_get_l2_hdr_length(data);
58
59
/*
60
* TODO: support vlan.
61
diff --git a/net/colo.h b/net/colo.h
62
index XXXXXXX..XXXXXXX 100644
63
--- a/net/colo.h
64
+++ b/net/colo.h
65
@@ -XXX,XX +XXX,XX @@
66
#include "qemu/jhash.h"
67
#include "qemu/timer.h"
68
#include "net/eth.h"
69
+#include "standard-headers/linux/virtio_net.h"
70
71
#define HASHTABLE_MAX_SIZE 16384
72
73
diff --git a/net/trace-events b/net/trace-events
74
index XXXXXXX..XXXXXXX 100644
75
--- a/net/trace-events
76
+++ b/net/trace-events
77
@@ -XXX,XX +XXX,XX @@ vhost_user_event(const char *chr, int event) "chr: %s got event: %d"
78
79
# colo.c
80
colo_proxy_main(const char *chr) ": %s"
81
-colo_proxy_main_vnet_info(const char *sta, int size) ": %s = %d"
82
+colo_proxy_main_vnet_info(const char *sta, uint32_t vnet_hdr, int size) ": %s pkt->vnet_hdr_len = %u, pkt->size = %d"
83
84
# colo-compare.c
85
colo_compare_main(const char *chr) ": %s"
86
--
87
2.7.4
diff view generated by jsdifflib
New patch
1
From: Zheyu Ma <zheyuma97@gmail.com>
1
2
3
The DMA engine is started by I/O access and then itself accesses the
4
I/O registers, triggering a reentrancy bug.
5
6
The following log can reveal it:
7
==5637==ERROR: AddressSanitizer: stack-overflow
8
#0 0x5595435f6078 in tulip_xmit_list_update qemu/hw/net/tulip.c:673
9
#1 0x5595435f204a in tulip_write qemu/hw/net/tulip.c:805:13
10
#2 0x559544637f86 in memory_region_write_accessor qemu/softmmu/memory.c:492:5
11
#3 0x5595446379fa in access_with_adjusted_size qemu/softmmu/memory.c:554:18
12
#4 0x5595446372fa in memory_region_dispatch_write qemu/softmmu/memory.c
13
#5 0x55954468b74c in flatview_write_continue qemu/softmmu/physmem.c:2825:23
14
#6 0x559544683662 in flatview_write qemu/softmmu/physmem.c:2867:12
15
#7 0x5595446833f3 in address_space_write qemu/softmmu/physmem.c:2963:18
16
#8 0x5595435fb082 in dma_memory_rw_relaxed qemu/include/sysemu/dma.h:87:12
17
#9 0x5595435fb082 in dma_memory_rw qemu/include/sysemu/dma.h:130:12
18
#10 0x5595435fb082 in dma_memory_write qemu/include/sysemu/dma.h:171:12
19
#11 0x5595435fb082 in stl_le_dma qemu/include/sysemu/dma.h:272:1
20
#12 0x5595435fb082 in stl_le_pci_dma qemu/include/hw/pci/pci.h:910:1
21
#13 0x5595435fb082 in tulip_desc_write qemu/hw/net/tulip.c:101:9
22
#14 0x5595435f7e3d in tulip_xmit_list_update qemu/hw/net/tulip.c:706:9
23
#15 0x5595435f204a in tulip_write qemu/hw/net/tulip.c:805:13
24
25
Fix this bug by restricting the DMA engine to memories regions.
26
27
Signed-off-by: Zheyu Ma <zheyuma97@gmail.com>
28
Signed-off-by: Jason Wang <jasowang@redhat.com>
29
---
30
hw/net/tulip.c | 4 ++--
31
1 file changed, 2 insertions(+), 2 deletions(-)
32
33
diff --git a/hw/net/tulip.c b/hw/net/tulip.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/net/tulip.c
36
+++ b/hw/net/tulip.c
37
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_pci_tulip = {
38
static void tulip_desc_read(TULIPState *s, hwaddr p,
39
struct tulip_descriptor *desc)
40
{
41
- const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
42
+ const MemTxAttrs attrs = { .memory = true };
43
44
if (s->csr[0] & CSR0_DBO) {
45
ldl_be_pci_dma(&s->dev, p, &desc->status, attrs);
46
@@ -XXX,XX +XXX,XX @@ static void tulip_desc_read(TULIPState *s, hwaddr p,
47
static void tulip_desc_write(TULIPState *s, hwaddr p,
48
struct tulip_descriptor *desc)
49
{
50
- const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
51
+ const MemTxAttrs attrs = { .memory = true };
52
53
if (s->csr[0] & CSR0_DBO) {
54
stl_be_pci_dma(&s->dev, p, desc->status, attrs);
55
--
56
2.7.4
diff view generated by jsdifflib