1
The following changes since commit 48033ad678ae2def43bf0d543a2c4c3d2a93feaf:
1
The following changes since commit eec398119fc6911d99412c37af06a6bc27871f85:
2
2
3
Merge remote-tracking branch 'remotes/vsementsov/tags/pull-nbd-2022-02-09-v2' into staging (2022-02-12 22:04:07 +0000)
3
Merge tag 'for_upstream' of git://git.kernel.org/pub/scm/virt/kvm/mst/qemu into staging (2022-05-16 16:31:01 -0700)
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 9d6267b240c114d1a3cd314a08fd6e1339d34b83:
9
for you to fetch changes up to 052c2579b89b0d87debe8b05594b5180f0fde87d:
10
10
11
net/eth: Don't consider ESP to be an IPv6 option header (2022-02-14 11:50:44 +0800)
11
tulip: Assign default MAC address if not specified (2022-05-17 16:48:23 +0800)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
14
15
----------------------------------------------------------------
15
----------------------------------------------------------------
16
Nick Hudson (1):
16
Helge Deller (1):
17
hw/net: e1000e: Clear ICR on read when using non MSI-X interrupts
17
tulip: Assign default MAC address if not specified
18
18
19
Peter Foley (2):
19
Vladislav Yaroshchuk (7):
20
net/tap: Set return code on failure
20
net/vmnet: add vmnet dependency and customizable option
21
net: Fix uninitialized data usage
21
net/vmnet: add vmnet backends to qapi/net
22
net/vmnet: implement shared mode (vmnet-shared)
23
net/vmnet: implement host mode (vmnet-host)
24
net/vmnet: implement bridged mode (vmnet-bridged)
25
net/vmnet: update qemu-options.hx
26
net/vmnet: update hmp-commands.hx
22
27
23
Philippe Mathieu-Daudé (1):
28
hmp-commands.hx | 6 +-
24
hw/net/vmxnet3: Log guest-triggerable errors using LOG_GUEST_ERROR
29
hw/net/tulip.c | 4 +-
25
30
meson.build | 16 +-
26
Rao Lei (1):
31
meson_options.txt | 2 +
27
net/filter: Optimize filter_send to coroutine
32
net/clients.h | 11 ++
28
33
net/meson.build | 7 +
29
Thomas Jansen (1):
34
net/net.c | 10 ++
30
net/eth: Don't consider ESP to be an IPv6 option header
35
net/vmnet-bridged.m | 152 +++++++++++++++++
31
36
net/vmnet-common.m | 378 ++++++++++++++++++++++++++++++++++++++++++
32
Zhang Chen (2):
37
net/vmnet-host.c | 128 ++++++++++++++
33
net/colo-compare.c: Optimize compare order for performance
38
net/vmnet-shared.c | 114 +++++++++++++
34
net/colo-compare.c: Update the default value comments
39
net/vmnet_int.h | 63 +++++++
35
40
qapi/net.json | 133 ++++++++++++++-
36
hw/net/e1000e_core.c | 5 ++++
41
qemu-options.hx | 25 +++
37
hw/net/trace-events | 1 +
42
scripts/meson-buildoptions.sh | 1 +
38
hw/net/vmxnet3.c | 4 +++-
43
15 files changed, 1044 insertions(+), 6 deletions(-)
39
net/colo-compare.c | 28 +++++++++++-----------
44
create mode 100644 net/vmnet-bridged.m
40
net/eth.c | 1 -
45
create mode 100644 net/vmnet-common.m
41
net/filter-mirror.c | 66 +++++++++++++++++++++++++++++++++++++++++-----------
46
create mode 100644 net/vmnet-host.c
42
net/tap-linux.c | 1 +
47
create mode 100644 net/vmnet-shared.c
43
net/tap.c | 1 +
48
create mode 100644 net/vmnet_int.h
44
8 files changed, 78 insertions(+), 29 deletions(-)
45
46
diff view generated by jsdifflib
1
From: Thomas Jansen <mithi@mithi.net>
1
From: Vladislav Yaroshchuk <vladislav.yaroshchuk@jetbrains.com>
2
2
3
The IPv6 option headers all have in common that they start with some
3
vmnet.framework dependency is added with 'vmnet' option
4
common fields, in particular the type of the next header followed by the
4
to enable or disable it. Default value is 'auto'.
5
extention header length. This is used to traverse the list of the
6
options. The ESP header does not follow that format, which can break the
7
IPv6 option header traversal code in eth_parse_ipv6_hdr().
8
5
9
The effect of that is that network interfaces such as vmxnet3 that use
6
used vmnet features are available since macOS 11.0,
10
the following call chain
7
but new backend can be built and work properly with
11
eth_is_ip6_extension_header_type
8
subset of them on 10.15 too.
12
eth_parse_ipv6_hdr
13
net_tx_pkt_parse_headers
14
net_tx_pkt_parse
15
vmxnet3_process_tx_queue
16
to send packets from the VM out to the host will drop packets of the
17
following structure:
18
Ethernet-Header(IPv6-Header(ESP(encrypted data)))
19
9
20
Note that not all types of network interfaces use the net_tx_pkt_parse
10
Reviewed-by: Akihiko Odaki <akihiko.odaki@gmail.com>
21
function though, leading to inconsistent behavior regarding sending
11
Tested-by: Akihiko Odaki <akihiko.odaki@gmail.com>
22
those packets. The e1000 network interface for example does not suffer
12
Signed-off-by: Vladislav Yaroshchuk <Vladislav.Yaroshchuk@jetbrains.com>
23
from this limitation.
24
25
By not considering ESP to be an IPv6 header we can allow sending those
26
packets out to the host on all types of network interfaces.
27
28
Fixes: 75020a702151 ("Common definitions for VMWARE devices")
29
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/149
30
Buglink: https://bugs.launchpad.net/qemu/+bug/1758091
31
Signed-off-by: Thomas Jansen <mithi@mithi.net>
32
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
Signed-off-by: Jason Wang <jasowang@redhat.com>
33
---
14
---
34
net/eth.c | 1 -
15
meson.build | 16 +++++++++++++++-
35
1 file changed, 1 deletion(-)
16
meson_options.txt | 2 ++
17
scripts/meson-buildoptions.sh | 1 +
18
3 files changed, 18 insertions(+), 1 deletion(-)
36
19
37
diff --git a/net/eth.c b/net/eth.c
20
diff --git a/meson.build b/meson.build
38
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
39
--- a/net/eth.c
22
--- a/meson.build
40
+++ b/net/eth.c
23
+++ b/meson.build
41
@@ -XXX,XX +XXX,XX @@ eth_is_ip6_extension_header_type(uint8_t hdr_type)
24
@@ -XXX,XX +XXX,XX @@ if cocoa.found() and get_option('gtk').enabled()
42
case IP6_HOP_BY_HOP:
25
error('Cocoa and GTK+ cannot be enabled at the same time')
43
case IP6_ROUTING:
26
endif
44
case IP6_FRAGMENT:
27
45
- case IP6_ESP:
28
+vmnet = dependency('appleframeworks', modules: 'vmnet', required: get_option('vmnet'))
46
case IP6_AUTHENTICATION:
29
+if vmnet.found() and not cc.has_header_symbol('vmnet/vmnet.h',
47
case IP6_DESTINATON:
30
+ 'VMNET_BRIDGED_MODE',
48
case IP6_MOBILITY:
31
+ dependencies: vmnet)
32
+ vmnet = not_found
33
+ if get_option('vmnet').enabled()
34
+ error('vmnet.framework API is outdated')
35
+ else
36
+ warning('vmnet.framework API is outdated, disabling')
37
+ endif
38
+endif
39
+
40
seccomp = not_found
41
if not get_option('seccomp').auto() or have_system or have_tools
42
seccomp = dependency('libseccomp', version: '>=2.3.0',
43
@@ -XXX,XX +XXX,XX @@ config_host_data.set('CONFIG_VHOST_KERNEL', have_vhost_kernel)
44
config_host_data.set('CONFIG_VHOST_USER', have_vhost_user)
45
config_host_data.set('CONFIG_VHOST_CRYPTO', have_vhost_user_crypto)
46
config_host_data.set('CONFIG_VHOST_VDPA', have_vhost_vdpa)
47
+config_host_data.set('CONFIG_VMNET', vmnet.found())
48
config_host_data.set('CONFIG_VHOST_USER_BLK_SERVER', have_vhost_user_blk_server)
49
config_host_data.set('CONFIG_PNG', png.found())
50
config_host_data.set('CONFIG_VNC', vnc.found())
51
@@ -XXX,XX +XXX,XX @@ summary(summary_info, bool_yn: true, section: 'Crypto')
52
# Libraries
53
summary_info = {}
54
if targetos == 'darwin'
55
- summary_info += {'Cocoa support': cocoa}
56
+ summary_info += {'Cocoa support': cocoa}
57
+ summary_info += {'vmnet.framework support': vmnet}
58
endif
59
summary_info += {'SDL support': sdl}
60
summary_info += {'SDL image support': sdl_image}
61
diff --git a/meson_options.txt b/meson_options.txt
62
index XXXXXXX..XXXXXXX 100644
63
--- a/meson_options.txt
64
+++ b/meson_options.txt
65
@@ -XXX,XX +XXX,XX @@ option('netmap', type : 'feature', value : 'auto',
66
description: 'netmap network backend support')
67
option('vde', type : 'feature', value : 'auto',
68
description: 'vde network backend support')
69
+option('vmnet', type : 'feature', value : 'auto',
70
+ description: 'vmnet.framework network backend support')
71
option('virglrenderer', type : 'feature', value : 'auto',
72
description: 'virgl rendering support')
73
option('png', type : 'feature', value : 'auto',
74
diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh
75
index XXXXXXX..XXXXXXX 100644
76
--- a/scripts/meson-buildoptions.sh
77
+++ b/scripts/meson-buildoptions.sh
78
@@ -XXX,XX +XXX,XX @@ meson_options_help() {
79
printf "%s\n" ' vhost-kernel vhost kernel backend support'
80
printf "%s\n" ' vhost-net vhost-net kernel acceleration support'
81
printf "%s\n" ' vhost-user vhost-user backend support'
82
+ printf "%s\n" ' vmnet vmnet.framework network backend support'
83
printf "%s\n" ' vhost-user-blk-server'
84
printf "%s\n" ' build vhost-user-blk server'
85
printf "%s\n" ' vhost-vdpa vhost-vdpa kernel backend support'
49
--
86
--
50
2.7.4
87
2.25.1
51
52
diff view generated by jsdifflib
1
From: Nick Hudson <skrll@netbsd.org>
1
From: Vladislav Yaroshchuk <vladislav.yaroshchuk@jetbrains.com>
2
2
3
In section 7.4.3 of the 82574 datasheet it states that
3
Create separate netdevs for each vmnet operating mode:
4
- vmnet-host
5
- vmnet-shared
6
- vmnet-bridged
4
7
5
"In systems that do not support MSI-X, reading the ICR
8
Reviewed-by: Akihiko Odaki <akihiko.odaki@gmail.com>
6
register clears it's bits..."
9
Tested-by: Akihiko Odaki <akihiko.odaki@gmail.com>
7
10
Acked-by: Markus Armbruster <armbru@redhat.com>
8
Some OSes rely on this.
11
Signed-off-by: Vladislav Yaroshchuk <Vladislav.Yaroshchuk@jetbrains.com>
9
10
Signed-off-by: Nick Hudson <skrll@netbsd.org>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
13
---
13
hw/net/e1000e_core.c | 5 +++++
14
net/clients.h | 11 ++++
14
hw/net/trace-events | 1 +
15
net/meson.build | 7 +++
15
2 files changed, 6 insertions(+)
16
net/net.c | 10 ++++
17
net/vmnet-bridged.m | 25 +++++++++
18
net/vmnet-common.m | 19 +++++++
19
net/vmnet-host.c | 24 ++++++++
20
net/vmnet-shared.c | 25 +++++++++
21
net/vmnet_int.h | 25 +++++++++
22
qapi/net.json | 133 +++++++++++++++++++++++++++++++++++++++++++-
23
9 files changed, 277 insertions(+), 2 deletions(-)
24
create mode 100644 net/vmnet-bridged.m
25
create mode 100644 net/vmnet-common.m
26
create mode 100644 net/vmnet-host.c
27
create mode 100644 net/vmnet-shared.c
28
create mode 100644 net/vmnet_int.h
16
29
17
diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
30
diff --git a/net/clients.h b/net/clients.h
18
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/net/e1000e_core.c
32
--- a/net/clients.h
20
+++ b/hw/net/e1000e_core.c
33
+++ b/net/clients.h
21
@@ -XXX,XX +XXX,XX @@ e1000e_mac_icr_read(E1000ECore *core, int index)
34
@@ -XXX,XX +XXX,XX @@ int net_init_vhost_user(const Netdev *netdev, const char *name,
22
core->mac[ICR] = 0;
35
23
}
36
int net_init_vhost_vdpa(const Netdev *netdev, const char *name,
24
37
NetClientState *peer, Error **errp);
25
+ if (!msix_enabled(core->owner)) {
38
+#ifdef CONFIG_VMNET
26
+ trace_e1000e_irq_icr_clear_nonmsix_icr_read();
39
+int net_init_vmnet_host(const Netdev *netdev, const char *name,
27
+ core->mac[ICR] = 0;
40
+ NetClientState *peer, Error **errp);
28
+ }
41
+
29
+
42
+int net_init_vmnet_shared(const Netdev *netdev, const char *name,
30
if ((core->mac[ICR] & E1000_ICR_ASSERTED) &&
43
+ NetClientState *peer, Error **errp);
31
(core->mac[CTRL_EXT] & E1000_CTRL_EXT_IAME)) {
44
+
32
trace_e1000e_irq_icr_clear_iame();
45
+int net_init_vmnet_bridged(const Netdev *netdev, const char *name,
33
diff --git a/hw/net/trace-events b/hw/net/trace-events
46
+ NetClientState *peer, Error **errp);
47
+#endif /* CONFIG_VMNET */
48
+
49
#endif /* QEMU_NET_CLIENTS_H */
50
diff --git a/net/meson.build b/net/meson.build
34
index XXXXXXX..XXXXXXX 100644
51
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/net/trace-events
52
--- a/net/meson.build
36
+++ b/hw/net/trace-events
53
+++ b/net/meson.build
37
@@ -XXX,XX +XXX,XX @@ e1000e_irq_write_ics(uint32_t val) "Adding ICR bits 0x%x"
54
@@ -XXX,XX +XXX,XX @@ if have_vhost_net_vdpa
38
e1000e_irq_icr_process_iame(void) "Clearing IMS bits due to IAME"
55
softmmu_ss.add(files('vhost-vdpa.c'))
39
e1000e_irq_read_ics(uint32_t ics) "Current ICS: 0x%x"
56
endif
40
e1000e_irq_read_ims(uint32_t ims) "Current IMS: 0x%x"
57
41
+e1000e_irq_icr_clear_nonmsix_icr_read(void) "Clearing ICR on read due to non MSI-X int"
58
+vmnet_files = files(
42
e1000e_irq_icr_read_entry(uint32_t icr) "Starting ICR read. Current ICR: 0x%x"
59
+ 'vmnet-common.m',
43
e1000e_irq_icr_read_exit(uint32_t icr) "Ending ICR read. Current ICR: 0x%x"
60
+ 'vmnet-bridged.m',
44
e1000e_irq_icr_clear_zero_ims(void) "Clearing ICR on read due to zero IMS"
61
+ 'vmnet-host.c',
62
+ 'vmnet-shared.c'
63
+)
64
+softmmu_ss.add(when: vmnet, if_true: vmnet_files)
65
subdir('can')
66
diff --git a/net/net.c b/net/net.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/net/net.c
69
+++ b/net/net.c
70
@@ -XXX,XX +XXX,XX @@ static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])(
71
#ifdef CONFIG_L2TPV3
72
[NET_CLIENT_DRIVER_L2TPV3] = net_init_l2tpv3,
73
#endif
74
+#ifdef CONFIG_VMNET
75
+ [NET_CLIENT_DRIVER_VMNET_HOST] = net_init_vmnet_host,
76
+ [NET_CLIENT_DRIVER_VMNET_SHARED] = net_init_vmnet_shared,
77
+ [NET_CLIENT_DRIVER_VMNET_BRIDGED] = net_init_vmnet_bridged,
78
+#endif /* CONFIG_VMNET */
79
};
80
81
82
@@ -XXX,XX +XXX,XX @@ void show_netdevs(void)
83
#endif
84
#ifdef CONFIG_VHOST_VDPA
85
"vhost-vdpa",
86
+#endif
87
+#ifdef CONFIG_VMNET
88
+ "vmnet-host",
89
+ "vmnet-shared",
90
+ "vmnet-bridged",
91
#endif
92
};
93
94
diff --git a/net/vmnet-bridged.m b/net/vmnet-bridged.m
95
new file mode 100644
96
index XXXXXXX..XXXXXXX
97
--- /dev/null
98
+++ b/net/vmnet-bridged.m
99
@@ -XXX,XX +XXX,XX @@
100
+/*
101
+ * vmnet-bridged.m
102
+ *
103
+ * Copyright(c) 2022 Vladislav Yaroshchuk <vladislav.yaroshchuk@jetbrains.com>
104
+ *
105
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
106
+ * See the COPYING file in the top-level directory.
107
+ *
108
+ */
109
+
110
+#include "qemu/osdep.h"
111
+#include "qapi/qapi-types-net.h"
112
+#include "vmnet_int.h"
113
+#include "clients.h"
114
+#include "qemu/error-report.h"
115
+#include "qapi/error.h"
116
+
117
+#include <vmnet/vmnet.h>
118
+
119
+int net_init_vmnet_bridged(const Netdev *netdev, const char *name,
120
+ NetClientState *peer, Error **errp)
121
+{
122
+ error_setg(errp, "vmnet-bridged is not implemented yet");
123
+ return -1;
124
+}
125
diff --git a/net/vmnet-common.m b/net/vmnet-common.m
126
new file mode 100644
127
index XXXXXXX..XXXXXXX
128
--- /dev/null
129
+++ b/net/vmnet-common.m
130
@@ -XXX,XX +XXX,XX @@
131
+/*
132
+ * vmnet-common.m - network client wrapper for Apple vmnet.framework
133
+ *
134
+ * Copyright(c) 2022 Vladislav Yaroshchuk <vladislav.yaroshchuk@jetbrains.com>
135
+ * Copyright(c) 2021 Phillip Tennen <phillip@axleos.com>
136
+ *
137
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
138
+ * See the COPYING file in the top-level directory.
139
+ *
140
+ */
141
+
142
+#include "qemu/osdep.h"
143
+#include "qapi/qapi-types-net.h"
144
+#include "vmnet_int.h"
145
+#include "clients.h"
146
+#include "qemu/error-report.h"
147
+#include "qapi/error.h"
148
+
149
+#include <vmnet/vmnet.h>
150
diff --git a/net/vmnet-host.c b/net/vmnet-host.c
151
new file mode 100644
152
index XXXXXXX..XXXXXXX
153
--- /dev/null
154
+++ b/net/vmnet-host.c
155
@@ -XXX,XX +XXX,XX @@
156
+/*
157
+ * vmnet-host.c
158
+ *
159
+ * Copyright(c) 2022 Vladislav Yaroshchuk <vladislav.yaroshchuk@jetbrains.com>
160
+ *
161
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
162
+ * See the COPYING file in the top-level directory.
163
+ *
164
+ */
165
+
166
+#include "qemu/osdep.h"
167
+#include "qapi/qapi-types-net.h"
168
+#include "vmnet_int.h"
169
+#include "clients.h"
170
+#include "qemu/error-report.h"
171
+#include "qapi/error.h"
172
+
173
+#include <vmnet/vmnet.h>
174
+
175
+int net_init_vmnet_host(const Netdev *netdev, const char *name,
176
+ NetClientState *peer, Error **errp) {
177
+ error_setg(errp, "vmnet-host is not implemented yet");
178
+ return -1;
179
+}
180
diff --git a/net/vmnet-shared.c b/net/vmnet-shared.c
181
new file mode 100644
182
index XXXXXXX..XXXXXXX
183
--- /dev/null
184
+++ b/net/vmnet-shared.c
185
@@ -XXX,XX +XXX,XX @@
186
+/*
187
+ * vmnet-shared.c
188
+ *
189
+ * Copyright(c) 2022 Vladislav Yaroshchuk <vladislav.yaroshchuk@jetbrains.com>
190
+ *
191
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
192
+ * See the COPYING file in the top-level directory.
193
+ *
194
+ */
195
+
196
+#include "qemu/osdep.h"
197
+#include "qapi/qapi-types-net.h"
198
+#include "vmnet_int.h"
199
+#include "clients.h"
200
+#include "qemu/error-report.h"
201
+#include "qapi/error.h"
202
+
203
+#include <vmnet/vmnet.h>
204
+
205
+int net_init_vmnet_shared(const Netdev *netdev, const char *name,
206
+ NetClientState *peer, Error **errp)
207
+{
208
+ error_setg(errp, "vmnet-shared is not implemented yet");
209
+ return -1;
210
+}
211
diff --git a/net/vmnet_int.h b/net/vmnet_int.h
212
new file mode 100644
213
index XXXXXXX..XXXXXXX
214
--- /dev/null
215
+++ b/net/vmnet_int.h
216
@@ -XXX,XX +XXX,XX @@
217
+/*
218
+ * vmnet_int.h
219
+ *
220
+ * Copyright(c) 2022 Vladislav Yaroshchuk <vladislav.yaroshchuk@jetbrains.com>
221
+ *
222
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
223
+ * See the COPYING file in the top-level directory.
224
+ *
225
+ */
226
+#ifndef VMNET_INT_H
227
+#define VMNET_INT_H
228
+
229
+#include "qemu/osdep.h"
230
+#include "vmnet_int.h"
231
+#include "clients.h"
232
+
233
+#include <vmnet/vmnet.h>
234
+
235
+typedef struct VmnetState {
236
+ NetClientState nc;
237
+
238
+} VmnetState;
239
+
240
+
241
+#endif /* VMNET_INT_H */
242
diff --git a/qapi/net.json b/qapi/net.json
243
index XXXXXXX..XXXXXXX 100644
244
--- a/qapi/net.json
245
+++ b/qapi/net.json
246
@@ -XXX,XX +XXX,XX @@
247
'*vhostdev': 'str',
248
'*queues': 'int' } }
249
250
+##
251
+# @NetdevVmnetHostOptions:
252
+#
253
+# vmnet (host mode) network backend.
254
+#
255
+# Allows the vmnet interface to communicate with other vmnet
256
+# interfaces that are in host mode and also with the host.
257
+#
258
+# @start-address: The starting IPv4 address to use for the interface.
259
+# Must be in the private IP range (RFC 1918). Must be
260
+# specified along with @end-address and @subnet-mask.
261
+# This address is used as the gateway address. The
262
+# subsequent address up to and including end-address are
263
+# placed in the DHCP pool.
264
+#
265
+# @end-address: The DHCP IPv4 range end address to use for the
266
+# interface. Must be in the private IP range (RFC 1918).
267
+# Must be specified along with @start-address and
268
+# @subnet-mask.
269
+#
270
+# @subnet-mask: The IPv4 subnet mask to use on the interface. Must
271
+# be specified along with @start-address and @subnet-mask.
272
+#
273
+# @isolated: Enable isolation for this interface. Interface isolation
274
+# ensures that vmnet interface is not able to communicate
275
+# with any other vmnet interfaces. Only communication with
276
+# host is allowed. Requires at least macOS Big Sur 11.0.
277
+#
278
+# @net-uuid: The identifier (UUID) to uniquely identify the isolated
279
+# network vmnet interface should be added to. If
280
+# set, no DHCP service is provided for this interface and
281
+# network communication is allowed only with other interfaces
282
+# added to this network identified by the UUID. Requires
283
+# at least macOS Big Sur 11.0.
284
+#
285
+# Since: 7.1
286
+##
287
+{ 'struct': 'NetdevVmnetHostOptions',
288
+ 'data': {
289
+ '*start-address': 'str',
290
+ '*end-address': 'str',
291
+ '*subnet-mask': 'str',
292
+ '*isolated': 'bool',
293
+ '*net-uuid': 'str' },
294
+ 'if': 'CONFIG_VMNET' }
295
+
296
+##
297
+# @NetdevVmnetSharedOptions:
298
+#
299
+# vmnet (shared mode) network backend.
300
+#
301
+# Allows traffic originating from the vmnet interface to reach the
302
+# Internet through a network address translator (NAT).
303
+# The vmnet interface can communicate with the host and with
304
+# other shared mode interfaces on the same subnet. If no DHCP
305
+# settings, subnet mask and IPv6 prefix specified, the interface can
306
+# communicate with any of other interfaces in shared mode.
307
+#
308
+# @start-address: The starting IPv4 address to use for the interface.
309
+# Must be in the private IP range (RFC 1918). Must be
310
+# specified along with @end-address and @subnet-mask.
311
+# This address is used as the gateway address. The
312
+# subsequent address up to and including end-address are
313
+# placed in the DHCP pool.
314
+#
315
+# @end-address: The DHCP IPv4 range end address to use for the
316
+# interface. Must be in the private IP range (RFC 1918).
317
+# Must be specified along with @start-address and @subnet-mask.
318
+#
319
+# @subnet-mask: The IPv4 subnet mask to use on the interface. Must
320
+# be specified along with @start-address and @subnet-mask.
321
+#
322
+# @isolated: Enable isolation for this interface. Interface isolation
323
+# ensures that vmnet interface is not able to communicate
324
+# with any other vmnet interfaces. Only communication with
325
+# host is allowed. Requires at least macOS Big Sur 11.0.
326
+#
327
+# @nat66-prefix: The IPv6 prefix to use into guest network. Must be a
328
+# unique local address i.e. start with fd00::/8 and have
329
+# length of 64.
330
+#
331
+# Since: 7.1
332
+##
333
+{ 'struct': 'NetdevVmnetSharedOptions',
334
+ 'data': {
335
+ '*start-address': 'str',
336
+ '*end-address': 'str',
337
+ '*subnet-mask': 'str',
338
+ '*isolated': 'bool',
339
+ '*nat66-prefix': 'str' },
340
+ 'if': 'CONFIG_VMNET' }
341
+
342
+##
343
+# @NetdevVmnetBridgedOptions:
344
+#
345
+# vmnet (bridged mode) network backend.
346
+#
347
+# Bridges the vmnet interface with a physical network interface.
348
+#
349
+# @ifname: The name of the physical interface to be bridged.
350
+#
351
+# @isolated: Enable isolation for this interface. Interface isolation
352
+# ensures that vmnet interface is not able to communicate
353
+# with any other vmnet interfaces. Only communication with
354
+# host is allowed. Requires at least macOS Big Sur 11.0.
355
+#
356
+# Since: 7.1
357
+##
358
+{ 'struct': 'NetdevVmnetBridgedOptions',
359
+ 'data': {
360
+ 'ifname': 'str',
361
+ '*isolated': 'bool' },
362
+ 'if': 'CONFIG_VMNET' }
363
+
364
##
365
# @NetClientDriver:
366
#
367
@@ -XXX,XX +XXX,XX @@
368
# Since: 2.7
369
#
370
# @vhost-vdpa since 5.1
371
+# @vmnet-host since 7.1
372
+# @vmnet-shared since 7.1
373
+# @vmnet-bridged since 7.1
374
##
375
{ 'enum': 'NetClientDriver',
376
'data': [ 'none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde',
377
- 'bridge', 'hubport', 'netmap', 'vhost-user', 'vhost-vdpa' ] }
378
+ 'bridge', 'hubport', 'netmap', 'vhost-user', 'vhost-vdpa',
379
+ { 'name': 'vmnet-host', 'if': 'CONFIG_VMNET' },
380
+ { 'name': 'vmnet-shared', 'if': 'CONFIG_VMNET' },
381
+ { 'name': 'vmnet-bridged', 'if': 'CONFIG_VMNET' }] }
382
383
##
384
# @Netdev:
385
@@ -XXX,XX +XXX,XX @@
386
# Since: 1.2
387
#
388
# 'l2tpv3' - since 2.1
389
+# 'vmnet-host' - since 7.1
390
+# 'vmnet-shared' - since 7.1
391
+# 'vmnet-bridged' - since 7.1
392
##
393
{ 'union': 'Netdev',
394
'base': { 'id': 'str', 'type': 'NetClientDriver' },
395
@@ -XXX,XX +XXX,XX @@
396
'hubport': 'NetdevHubPortOptions',
397
'netmap': 'NetdevNetmapOptions',
398
'vhost-user': 'NetdevVhostUserOptions',
399
- 'vhost-vdpa': 'NetdevVhostVDPAOptions' } }
400
+ 'vhost-vdpa': 'NetdevVhostVDPAOptions',
401
+ 'vmnet-host': { 'type': 'NetdevVmnetHostOptions',
402
+ 'if': 'CONFIG_VMNET' },
403
+ 'vmnet-shared': { 'type': 'NetdevVmnetSharedOptions',
404
+ 'if': 'CONFIG_VMNET' },
405
+ 'vmnet-bridged': { 'type': 'NetdevVmnetBridgedOptions',
406
+ 'if': 'CONFIG_VMNET' } } }
407
408
##
409
# @RxState:
45
--
410
--
46
2.7.4
411
2.25.1
47
48
diff view generated by jsdifflib
1
From: Zhang Chen <chen.zhang@intel.com>
1
From: Vladislav Yaroshchuk <vladislav.yaroshchuk@jetbrains.com>
2
2
3
Make the comments consistent with the REGULAR_PACKET_CHECK_MS.
3
Interaction with vmnet.framework in different modes
4
differs only on configuration stage, so we can create
5
common `send`, `receive`, etc. procedures and reuse them.
4
6
5
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
7
Reviewed-by: Akihiko Odaki <akihiko.odaki@gmail.com>
8
Tested-by: Akihiko Odaki <akihiko.odaki@gmail.com>
9
Signed-off-by: Phillip Tennen <phillip@axleos.com>
10
Signed-off-by: Vladislav Yaroshchuk <Vladislav.Yaroshchuk@jetbrains.com>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
---
12
---
8
net/colo-compare.c | 2 +-
13
net/vmnet-common.m | 359 +++++++++++++++++++++++++++++++++++++++++++++
9
1 file changed, 1 insertion(+), 1 deletion(-)
14
net/vmnet-shared.c | 97 +++++++++++-
15
net/vmnet_int.h | 40 ++++-
16
3 files changed, 491 insertions(+), 5 deletions(-)
10
17
11
diff --git a/net/colo-compare.c b/net/colo-compare.c
18
diff --git a/net/vmnet-common.m b/net/vmnet-common.m
12
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
13
--- a/net/colo-compare.c
20
--- a/net/vmnet-common.m
14
+++ b/net/colo-compare.c
21
+++ b/net/vmnet-common.m
15
@@ -XXX,XX +XXX,XX @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
22
@@ -XXX,XX +XXX,XX @@
16
}
23
*/
17
24
18
if (!s->expired_scan_cycle) {
25
#include "qemu/osdep.h"
19
- /* Set default value to 3000 MS */
26
+#include "qemu/main-loop.h"
20
+ /* Set default value to 1000 MS */
27
+#include "qemu/log.h"
21
s->expired_scan_cycle = REGULAR_PACKET_CHECK_MS;
28
#include "qapi/qapi-types-net.h"
22
}
29
#include "vmnet_int.h"
23
30
#include "clients.h"
31
@@ -XXX,XX +XXX,XX @@
32
#include "qapi/error.h"
33
34
#include <vmnet/vmnet.h>
35
+#include <dispatch/dispatch.h>
36
+
37
+
38
+static void vmnet_send_completed(NetClientState *nc, ssize_t len);
39
+
40
+
41
+const char *vmnet_status_map_str(vmnet_return_t status)
42
+{
43
+ switch (status) {
44
+ case VMNET_SUCCESS:
45
+ return "success";
46
+ case VMNET_FAILURE:
47
+ return "general failure (possibly not enough privileges)";
48
+ case VMNET_MEM_FAILURE:
49
+ return "memory allocation failure";
50
+ case VMNET_INVALID_ARGUMENT:
51
+ return "invalid argument specified";
52
+ case VMNET_SETUP_INCOMPLETE:
53
+ return "interface setup is not complete";
54
+ case VMNET_INVALID_ACCESS:
55
+ return "invalid access, permission denied";
56
+ case VMNET_PACKET_TOO_BIG:
57
+ return "packet size is larger than MTU";
58
+ case VMNET_BUFFER_EXHAUSTED:
59
+ return "buffers exhausted in kernel";
60
+ case VMNET_TOO_MANY_PACKETS:
61
+ return "packet count exceeds limit";
62
+#if defined(MAC_OS_VERSION_11_0) && \
63
+ MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_11_0
64
+ case VMNET_SHARING_SERVICE_BUSY:
65
+ return "conflict, sharing service is in use";
66
+#endif
67
+ default:
68
+ return "unknown vmnet error";
69
+ }
70
+}
71
+
72
+
73
+/**
74
+ * Write packets from QEMU to vmnet interface.
75
+ *
76
+ * vmnet.framework supports iov, but writing more than
77
+ * one iov into vmnet interface fails with
78
+ * 'VMNET_INVALID_ARGUMENT'. Collecting provided iovs into
79
+ * one and passing it to vmnet works fine. That's the
80
+ * reason why receive_iov() left unimplemented. But it still
81
+ * works with good performance having .receive() only.
82
+ */
83
+ssize_t vmnet_receive_common(NetClientState *nc,
84
+ const uint8_t *buf,
85
+ size_t size)
86
+{
87
+ VmnetState *s = DO_UPCAST(VmnetState, nc, nc);
88
+ struct vmpktdesc packet;
89
+ struct iovec iov;
90
+ int pkt_cnt;
91
+ vmnet_return_t if_status;
92
+
93
+ if (size > s->max_packet_size) {
94
+ warn_report("vmnet: packet is too big, %zu > %" PRIu64,
95
+ packet.vm_pkt_size,
96
+ s->max_packet_size);
97
+ return -1;
98
+ }
99
+
100
+ iov.iov_base = (char *) buf;
101
+ iov.iov_len = size;
102
+
103
+ packet.vm_pkt_iovcnt = 1;
104
+ packet.vm_flags = 0;
105
+ packet.vm_pkt_size = size;
106
+ packet.vm_pkt_iov = &iov;
107
+ pkt_cnt = 1;
108
+
109
+ if_status = vmnet_write(s->vmnet_if, &packet, &pkt_cnt);
110
+ if (if_status != VMNET_SUCCESS) {
111
+ error_report("vmnet: write error: %s\n",
112
+ vmnet_status_map_str(if_status));
113
+ return -1;
114
+ }
115
+
116
+ if (pkt_cnt) {
117
+ return size;
118
+ }
119
+ return 0;
120
+}
121
+
122
+
123
+/**
124
+ * Read packets from vmnet interface and write them
125
+ * to temporary buffers in VmnetState.
126
+ *
127
+ * Returns read packets number (may be 0) on success,
128
+ * -1 on error
129
+ */
130
+static int vmnet_read_packets(VmnetState *s)
131
+{
132
+ assert(s->packets_send_current_pos == s->packets_send_end_pos);
133
+
134
+ struct vmpktdesc *packets = s->packets_buf;
135
+ vmnet_return_t status;
136
+ int i;
137
+
138
+ /* Read as many packets as present */
139
+ s->packets_send_current_pos = 0;
140
+ s->packets_send_end_pos = VMNET_PACKETS_LIMIT;
141
+ for (i = 0; i < s->packets_send_end_pos; ++i) {
142
+ packets[i].vm_pkt_size = s->max_packet_size;
143
+ packets[i].vm_pkt_iovcnt = 1;
144
+ packets[i].vm_flags = 0;
145
+ }
146
+
147
+ status = vmnet_read(s->vmnet_if, packets, &s->packets_send_end_pos);
148
+ if (status != VMNET_SUCCESS) {
149
+ error_printf("vmnet: read failed: %s\n",
150
+ vmnet_status_map_str(status));
151
+ s->packets_send_current_pos = 0;
152
+ s->packets_send_end_pos = 0;
153
+ return -1;
154
+ }
155
+ return s->packets_send_end_pos;
156
+}
157
+
158
+
159
+/**
160
+ * Write packets from temporary buffers in VmnetState
161
+ * to QEMU.
162
+ */
163
+static void vmnet_write_packets_to_qemu(VmnetState *s)
164
+{
165
+ while (s->packets_send_current_pos < s->packets_send_end_pos) {
166
+ ssize_t size = qemu_send_packet_async(&s->nc,
167
+ s->iov_buf[s->packets_send_current_pos].iov_base,
168
+ s->packets_buf[s->packets_send_current_pos].vm_pkt_size,
169
+ vmnet_send_completed);
170
+
171
+ if (size == 0) {
172
+ /* QEMU is not ready to consume more packets -
173
+ * stop and wait for completion callback call */
174
+ return;
175
+ }
176
+ ++s->packets_send_current_pos;
177
+ }
178
+}
179
+
180
+
181
+/**
182
+ * Bottom half callback that transfers packets from vmnet interface
183
+ * to QEMU.
184
+ *
185
+ * The process of transferring packets is three-staged:
186
+ * 1. Handle vmnet event;
187
+ * 2. Read packets from vmnet interface into temporary buffer;
188
+ * 3. Write packets from temporary buffer to QEMU.
189
+ *
190
+ * QEMU may suspend this process on the last stage, returning 0 from
191
+ * qemu_send_packet_async function. If this happens, we should
192
+ * respectfully wait until it is ready to consume more packets,
193
+ * write left ones in temporary buffer and only after this
194
+ * continue reading more packets from vmnet interface.
195
+ *
196
+ * Packets to be transferred are stored into packets_buf,
197
+ * in the window [packets_send_current_pos..packets_send_end_pos)
198
+ * including current_pos, excluding end_pos.
199
+ *
200
+ * Thus, if QEMU is not ready, buffer is not read and
201
+ * packets_send_current_pos < packets_send_end_pos.
202
+ */
203
+static void vmnet_send_bh(void *opaque)
204
+{
205
+ NetClientState *nc = (NetClientState *) opaque;
206
+ VmnetState *s = DO_UPCAST(VmnetState, nc, nc);
207
+
208
+ /*
209
+ * Do nothing if QEMU is not ready - wait
210
+ * for completion callback invocation
211
+ */
212
+ if (s->packets_send_current_pos < s->packets_send_end_pos) {
213
+ return;
214
+ }
215
+
216
+ /* Read packets from vmnet interface */
217
+ if (vmnet_read_packets(s) > 0) {
218
+ /* Send them to QEMU */
219
+ vmnet_write_packets_to_qemu(s);
220
+ }
221
+}
222
+
223
+
224
+/**
225
+ * Completion callback to be invoked by QEMU when it becomes
226
+ * ready to consume more packets.
227
+ */
228
+static void vmnet_send_completed(NetClientState *nc, ssize_t len)
229
+{
230
+ VmnetState *s = DO_UPCAST(VmnetState, nc, nc);
231
+
232
+ /* Callback is invoked eq queued packet is sent */
233
+ ++s->packets_send_current_pos;
234
+
235
+ /* Complete sending packets left in VmnetState buffers */
236
+ vmnet_write_packets_to_qemu(s);
237
+
238
+ /* And read new ones from vmnet if VmnetState buffer is ready */
239
+ if (s->packets_send_current_pos < s->packets_send_end_pos) {
240
+ qemu_bh_schedule(s->send_bh);
241
+ }
242
+}
243
+
244
+
245
+static void vmnet_bufs_init(VmnetState *s)
246
+{
247
+ struct vmpktdesc *packets = s->packets_buf;
248
+ struct iovec *iov = s->iov_buf;
249
+ int i;
250
+
251
+ for (i = 0; i < VMNET_PACKETS_LIMIT; ++i) {
252
+ iov[i].iov_len = s->max_packet_size;
253
+ iov[i].iov_base = g_malloc0(iov[i].iov_len);
254
+ packets[i].vm_pkt_iov = iov + i;
255
+ }
256
+}
257
+
258
+
259
+int vmnet_if_create(NetClientState *nc,
260
+ xpc_object_t if_desc,
261
+ Error **errp)
262
+{
263
+ VmnetState *s = DO_UPCAST(VmnetState, nc, nc);
264
+ dispatch_semaphore_t if_created_sem = dispatch_semaphore_create(0);
265
+ __block vmnet_return_t if_status;
266
+
267
+ s->if_queue = dispatch_queue_create(
268
+ "org.qemu.vmnet.if_queue",
269
+ DISPATCH_QUEUE_SERIAL
270
+ );
271
+
272
+ xpc_dictionary_set_bool(
273
+ if_desc,
274
+ vmnet_allocate_mac_address_key,
275
+ false
276
+ );
277
+
278
+#ifdef DEBUG
279
+ qemu_log("vmnet.start.interface_desc:\n");
280
+ xpc_dictionary_apply(if_desc,
281
+ ^bool(const char *k, xpc_object_t v) {
282
+ char *desc = xpc_copy_description(v);
283
+ qemu_log(" %s=%s\n", k, desc);
284
+ free(desc);
285
+ return true;
286
+ });
287
+#endif /* DEBUG */
288
+
289
+ s->vmnet_if = vmnet_start_interface(
290
+ if_desc,
291
+ s->if_queue,
292
+ ^(vmnet_return_t status, xpc_object_t interface_param) {
293
+ if_status = status;
294
+ if (status != VMNET_SUCCESS || !interface_param) {
295
+ dispatch_semaphore_signal(if_created_sem);
296
+ return;
297
+ }
298
+
299
+#ifdef DEBUG
300
+ qemu_log("vmnet.start.interface_param:\n");
301
+ xpc_dictionary_apply(interface_param,
302
+ ^bool(const char *k, xpc_object_t v) {
303
+ char *desc = xpc_copy_description(v);
304
+ qemu_log(" %s=%s\n", k, desc);
305
+ free(desc);
306
+ return true;
307
+ });
308
+#endif /* DEBUG */
309
+
310
+ s->mtu = xpc_dictionary_get_uint64(
311
+ interface_param,
312
+ vmnet_mtu_key);
313
+ s->max_packet_size = xpc_dictionary_get_uint64(
314
+ interface_param,
315
+ vmnet_max_packet_size_key);
316
+
317
+ dispatch_semaphore_signal(if_created_sem);
318
+ });
319
+
320
+ if (s->vmnet_if == NULL) {
321
+ dispatch_release(s->if_queue);
322
+ dispatch_release(if_created_sem);
323
+ error_setg(errp,
324
+ "unable to create interface with requested params");
325
+ return -1;
326
+ }
327
+
328
+ dispatch_semaphore_wait(if_created_sem, DISPATCH_TIME_FOREVER);
329
+ dispatch_release(if_created_sem);
330
+
331
+ if (if_status != VMNET_SUCCESS) {
332
+ dispatch_release(s->if_queue);
333
+ error_setg(errp,
334
+ "cannot create vmnet interface: %s",
335
+ vmnet_status_map_str(if_status));
336
+ return -1;
337
+ }
338
+
339
+ s->send_bh = aio_bh_new(qemu_get_aio_context(), vmnet_send_bh, nc);
340
+ vmnet_bufs_init(s);
341
+
342
+ s->packets_send_current_pos = 0;
343
+ s->packets_send_end_pos = 0;
344
+
345
+ vmnet_interface_set_event_callback(
346
+ s->vmnet_if,
347
+ VMNET_INTERFACE_PACKETS_AVAILABLE,
348
+ s->if_queue,
349
+ ^(interface_event_t event_id, xpc_object_t event) {
350
+ assert(event_id == VMNET_INTERFACE_PACKETS_AVAILABLE);
351
+ /*
352
+ * This function is being called from a non qemu thread, so
353
+ * we only schedule a BH, and do the rest of the io completion
354
+ * handling from vmnet_send_bh() which runs in a qemu context.
355
+ */
356
+ qemu_bh_schedule(s->send_bh);
357
+ });
358
+
359
+ return 0;
360
+}
361
+
362
+
363
+void vmnet_cleanup_common(NetClientState *nc)
364
+{
365
+ VmnetState *s = DO_UPCAST(VmnetState, nc, nc);
366
+ dispatch_semaphore_t if_stopped_sem;
367
+
368
+ if (s->vmnet_if == NULL) {
369
+ return;
370
+ }
371
+
372
+ if_stopped_sem = dispatch_semaphore_create(0);
373
+ vmnet_stop_interface(
374
+ s->vmnet_if,
375
+ s->if_queue,
376
+ ^(vmnet_return_t status) {
377
+ assert(status == VMNET_SUCCESS);
378
+ dispatch_semaphore_signal(if_stopped_sem);
379
+ });
380
+ dispatch_semaphore_wait(if_stopped_sem, DISPATCH_TIME_FOREVER);
381
+
382
+ qemu_purge_queued_packets(nc);
383
+
384
+ qemu_bh_delete(s->send_bh);
385
+ dispatch_release(if_stopped_sem);
386
+ dispatch_release(s->if_queue);
387
+
388
+ for (int i = 0; i < VMNET_PACKETS_LIMIT; ++i) {
389
+ g_free(s->iov_buf[i].iov_base);
390
+ }
391
+}
392
diff --git a/net/vmnet-shared.c b/net/vmnet-shared.c
393
index XXXXXXX..XXXXXXX 100644
394
--- a/net/vmnet-shared.c
395
+++ b/net/vmnet-shared.c
396
@@ -XXX,XX +XXX,XX @@
397
398
#include "qemu/osdep.h"
399
#include "qapi/qapi-types-net.h"
400
+#include "qapi/error.h"
401
#include "vmnet_int.h"
402
#include "clients.h"
403
-#include "qemu/error-report.h"
404
-#include "qapi/error.h"
405
406
#include <vmnet/vmnet.h>
407
408
+
409
+static bool validate_options(const Netdev *netdev, Error **errp)
410
+{
411
+ const NetdevVmnetSharedOptions *options = &(netdev->u.vmnet_shared);
412
+
413
+#if !defined(MAC_OS_VERSION_11_0) || \
414
+ MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_VERSION_11_0
415
+ if (options->has_isolated) {
416
+ error_setg(errp,
417
+ "vmnet-shared.isolated feature is "
418
+ "unavailable: outdated vmnet.framework API");
419
+ return false;
420
+ }
421
+#endif
422
+
423
+ if ((options->has_start_address ||
424
+ options->has_end_address ||
425
+ options->has_subnet_mask) &&
426
+ !(options->has_start_address &&
427
+ options->has_end_address &&
428
+ options->has_subnet_mask)) {
429
+ error_setg(errp,
430
+ "'start-address', 'end-address', 'subnet-mask' "
431
+ "should be provided together"
432
+ );
433
+ return false;
434
+ }
435
+
436
+ return true;
437
+}
438
+
439
+static xpc_object_t build_if_desc(const Netdev *netdev)
440
+{
441
+ const NetdevVmnetSharedOptions *options = &(netdev->u.vmnet_shared);
442
+ xpc_object_t if_desc = xpc_dictionary_create(NULL, NULL, 0);
443
+
444
+ xpc_dictionary_set_uint64(
445
+ if_desc,
446
+ vmnet_operation_mode_key,
447
+ VMNET_SHARED_MODE
448
+ );
449
+
450
+ if (options->has_nat66_prefix) {
451
+ xpc_dictionary_set_string(if_desc,
452
+ vmnet_nat66_prefix_key,
453
+ options->nat66_prefix);
454
+ }
455
+
456
+ if (options->has_start_address) {
457
+ xpc_dictionary_set_string(if_desc,
458
+ vmnet_start_address_key,
459
+ options->start_address);
460
+ xpc_dictionary_set_string(if_desc,
461
+ vmnet_end_address_key,
462
+ options->end_address);
463
+ xpc_dictionary_set_string(if_desc,
464
+ vmnet_subnet_mask_key,
465
+ options->subnet_mask);
466
+ }
467
+
468
+#if defined(MAC_OS_VERSION_11_0) && \
469
+ MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_11_0
470
+ xpc_dictionary_set_bool(
471
+ if_desc,
472
+ vmnet_enable_isolation_key,
473
+ options->isolated
474
+ );
475
+#endif
476
+
477
+ return if_desc;
478
+}
479
+
480
+static NetClientInfo net_vmnet_shared_info = {
481
+ .type = NET_CLIENT_DRIVER_VMNET_SHARED,
482
+ .size = sizeof(VmnetState),
483
+ .receive = vmnet_receive_common,
484
+ .cleanup = vmnet_cleanup_common,
485
+};
486
+
487
int net_init_vmnet_shared(const Netdev *netdev, const char *name,
488
NetClientState *peer, Error **errp)
489
{
490
- error_setg(errp, "vmnet-shared is not implemented yet");
491
- return -1;
492
+ NetClientState *nc = qemu_new_net_client(&net_vmnet_shared_info,
493
+ peer, "vmnet-shared", name);
494
+ xpc_object_t if_desc;
495
+ int result = -1;
496
+
497
+ if (!validate_options(netdev, errp)) {
498
+ return result;
499
+ }
500
+
501
+ if_desc = build_if_desc(netdev);
502
+ result = vmnet_if_create(nc, if_desc, errp);
503
+ xpc_release(if_desc);
504
+ return result;
505
}
506
diff --git a/net/vmnet_int.h b/net/vmnet_int.h
507
index XXXXXXX..XXXXXXX 100644
508
--- a/net/vmnet_int.h
509
+++ b/net/vmnet_int.h
510
@@ -XXX,XX +XXX,XX @@
511
#include "clients.h"
512
513
#include <vmnet/vmnet.h>
514
+#include <dispatch/dispatch.h>
515
+
516
+/**
517
+ * From vmnet.framework documentation
518
+ *
519
+ * Each read/write call allows up to 200 packets to be
520
+ * read or written for a maximum of 256KB.
521
+ *
522
+ * Each packet written should be a complete
523
+ * ethernet frame.
524
+ *
525
+ * https://developer.apple.com/documentation/vmnet
526
+ */
527
+#define VMNET_PACKETS_LIMIT 200
528
529
typedef struct VmnetState {
530
- NetClientState nc;
531
+ NetClientState nc;
532
+ interface_ref vmnet_if;
533
+
534
+ uint64_t mtu;
535
+ uint64_t max_packet_size;
536
537
+ dispatch_queue_t if_queue;
538
+
539
+ QEMUBH *send_bh;
540
+
541
+ struct vmpktdesc packets_buf[VMNET_PACKETS_LIMIT];
542
+ int packets_send_current_pos;
543
+ int packets_send_end_pos;
544
+
545
+ struct iovec iov_buf[VMNET_PACKETS_LIMIT];
546
} VmnetState;
547
548
+const char *vmnet_status_map_str(vmnet_return_t status);
549
+
550
+int vmnet_if_create(NetClientState *nc,
551
+ xpc_object_t if_desc,
552
+ Error **errp);
553
+
554
+ssize_t vmnet_receive_common(NetClientState *nc,
555
+ const uint8_t *buf,
556
+ size_t size);
557
+
558
+void vmnet_cleanup_common(NetClientState *nc);
559
560
#endif /* VMNET_INT_H */
24
--
561
--
25
2.7.4
562
2.25.1
26
27
diff view generated by jsdifflib
1
From: Zhang Chen <chen.zhang@intel.com>
1
From: Vladislav Yaroshchuk <vladislav.yaroshchuk@jetbrains.com>
2
2
3
COLO-compare use the glib function g_queue_find_custom to dump
3
Reviewed-by: Akihiko Odaki <akihiko.odaki@gmail.com>
4
another VM's networking packet to compare. But this function always
4
Tested-by: Akihiko Odaki <akihiko.odaki@gmail.com>
5
start find from the queue->head(here is the newest packet), It will
5
Signed-off-by: Vladislav Yaroshchuk <Vladislav.Yaroshchuk@jetbrains.com>
6
reduce the success rate of comparison. So this patch reversed
7
the order of the queues for performance.
8
9
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
10
Reported-by: leirao <lei.rao@intel.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
7
---
13
net/colo-compare.c | 26 +++++++++++++-------------
8
net/vmnet-host.c | 116 ++++++++++++++++++++++++++++++++++++++++++++---
14
1 file changed, 13 insertions(+), 13 deletions(-)
9
1 file changed, 110 insertions(+), 6 deletions(-)
15
10
16
diff --git a/net/colo-compare.c b/net/colo-compare.c
11
diff --git a/net/vmnet-host.c b/net/vmnet-host.c
17
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
18
--- a/net/colo-compare.c
13
--- a/net/vmnet-host.c
19
+++ b/net/colo-compare.c
14
+++ b/net/vmnet-host.c
20
@@ -XXX,XX +XXX,XX @@ static void colo_compare_inconsistency_notify(CompareState *s)
15
@@ -XXX,XX +XXX,XX @@
21
/* Use restricted to colo_insert_packet() */
16
*/
22
static gint seq_sorter(Packet *a, Packet *b, gpointer data)
17
23
{
18
#include "qemu/osdep.h"
24
- return a->tcp_seq - b->tcp_seq;
19
+#include "qemu/uuid.h"
25
+ return b->tcp_seq - a->tcp_seq;
20
#include "qapi/qapi-types-net.h"
26
}
21
-#include "vmnet_int.h"
27
22
-#include "clients.h"
28
static void fill_pkt_tcp_info(void *data, uint32_t *max_ack)
23
-#include "qemu/error-report.h"
29
@@ -XXX,XX +XXX,XX @@ pri:
24
#include "qapi/error.h"
30
if (g_queue_is_empty(&conn->primary_list)) {
25
+#include "clients.h"
31
return;
26
+#include "vmnet_int.h"
32
}
27
33
- ppkt = g_queue_pop_head(&conn->primary_list);
28
#include <vmnet/vmnet.h>
34
+ ppkt = g_queue_pop_tail(&conn->primary_list);
29
35
sec:
30
+
36
if (g_queue_is_empty(&conn->secondary_list)) {
31
+static bool validate_options(const Netdev *netdev, Error **errp)
37
- g_queue_push_head(&conn->primary_list, ppkt);
32
+{
38
+ g_queue_push_tail(&conn->primary_list, ppkt);
33
+ const NetdevVmnetHostOptions *options = &(netdev->u.vmnet_host);
39
return;
34
+
40
}
35
+#if defined(MAC_OS_VERSION_11_0) && \
41
- spkt = g_queue_pop_head(&conn->secondary_list);
36
+ MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_11_0
42
+ spkt = g_queue_pop_tail(&conn->secondary_list);
37
+
43
38
+ QemuUUID net_uuid;
44
if (ppkt->tcp_seq == ppkt->seq_end) {
39
+ if (options->has_net_uuid &&
45
colo_release_primary_pkt(s, ppkt);
40
+ qemu_uuid_parse(options->net_uuid, &net_uuid) < 0) {
46
@@ -XXX,XX +XXX,XX @@ sec:
41
+ error_setg(errp, "Invalid UUID provided in 'net-uuid'");
47
}
42
+ return false;
48
}
43
+ }
49
if (!ppkt) {
44
+#else
50
- g_queue_push_head(&conn->secondary_list, spkt);
45
+ if (options->has_isolated) {
51
+ g_queue_push_tail(&conn->secondary_list, spkt);
46
+ error_setg(errp,
52
goto pri;
47
+ "vmnet-host.isolated feature is "
53
}
48
+ "unavailable: outdated vmnet.framework API");
54
}
49
+ return false;
55
@@ -XXX,XX +XXX,XX @@ sec:
50
+ }
56
if (mark == COLO_COMPARE_FREE_PRIMARY) {
51
+
57
conn->compare_seq = ppkt->seq_end;
52
+ if (options->has_net_uuid) {
58
colo_release_primary_pkt(s, ppkt);
53
+ error_setg(errp,
59
- g_queue_push_head(&conn->secondary_list, spkt);
54
+ "vmnet-host.net-uuid feature is "
60
+ g_queue_push_tail(&conn->secondary_list, spkt);
55
+ "unavailable: outdated vmnet.framework API");
61
goto pri;
56
+ return false;
62
} else if (mark == COLO_COMPARE_FREE_SECONDARY) {
57
+ }
63
conn->compare_seq = spkt->seq_end;
58
+#endif
64
@@ -XXX,XX +XXX,XX @@ sec:
59
+
65
goto pri;
60
+ if ((options->has_start_address ||
66
}
61
+ options->has_end_address ||
67
} else {
62
+ options->has_subnet_mask) &&
68
- g_queue_push_head(&conn->primary_list, ppkt);
63
+ !(options->has_start_address &&
69
- g_queue_push_head(&conn->secondary_list, spkt);
64
+ options->has_end_address &&
70
+ g_queue_push_tail(&conn->primary_list, ppkt);
65
+ options->has_subnet_mask)) {
71
+ g_queue_push_tail(&conn->secondary_list, spkt);
66
+ error_setg(errp,
72
67
+ "'start-address', 'end-address', 'subnet-mask' "
73
#ifdef DEBUG_COLO_PACKETS
68
+ "should be provided together");
74
qemu_hexdump(stderr, "colo-compare ppkt", ppkt->data, ppkt->size);
69
+ return false;
75
@@ -XXX,XX +XXX,XX @@ static void colo_compare_packet(CompareState *s, Connection *conn,
70
+ }
76
71
+
77
while (!g_queue_is_empty(&conn->primary_list) &&
72
+ return true;
78
!g_queue_is_empty(&conn->secondary_list)) {
73
+}
79
- pkt = g_queue_pop_head(&conn->primary_list);
74
+
80
+ pkt = g_queue_pop_tail(&conn->primary_list);
75
+static xpc_object_t build_if_desc(const Netdev *netdev)
81
result = g_queue_find_custom(&conn->secondary_list,
76
+{
82
pkt, (GCompareFunc)HandlePacket);
77
+ const NetdevVmnetHostOptions *options = &(netdev->u.vmnet_host);
83
78
+ xpc_object_t if_desc = xpc_dictionary_create(NULL, NULL, 0);
84
@@ -XXX,XX +XXX,XX @@ static void colo_compare_packet(CompareState *s, Connection *conn,
79
+
85
* timeout, it will trigger a checkpoint request.
80
+ xpc_dictionary_set_uint64(if_desc,
86
*/
81
+ vmnet_operation_mode_key,
87
trace_colo_compare_main("packet different");
82
+ VMNET_HOST_MODE);
88
- g_queue_push_head(&conn->primary_list, pkt);
83
+
89
+ g_queue_push_tail(&conn->primary_list, pkt);
84
+#if defined(MAC_OS_VERSION_11_0) && \
90
85
+ MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_11_0
91
colo_compare_inconsistency_notify(s);
86
+
92
break;
87
+ xpc_dictionary_set_bool(if_desc,
93
@@ -XXX,XX +XXX,XX @@ static int compare_chr_send(CompareState *s,
88
+ vmnet_enable_isolation_key,
94
entry->buf = g_malloc(size);
89
+ options->isolated);
95
memcpy(entry->buf, buf, size);
90
+
96
}
91
+ QemuUUID net_uuid;
97
- g_queue_push_head(&sendco->send_list, entry);
92
+ if (options->has_net_uuid) {
98
+ g_queue_push_tail(&sendco->send_list, entry);
93
+ qemu_uuid_parse(options->net_uuid, &net_uuid);
99
94
+ xpc_dictionary_set_uuid(if_desc,
100
if (sendco->done) {
95
+ vmnet_network_identifier_key,
101
sendco->co = qemu_coroutine_create(_compare_chr_send, sendco);
96
+ net_uuid.data);
102
@@ -XXX,XX +XXX,XX @@ static void colo_flush_packets(void *opaque, void *user_data)
97
+ }
103
Packet *pkt = NULL;
98
+#endif
104
99
+
105
while (!g_queue_is_empty(&conn->primary_list)) {
100
+ if (options->has_start_address) {
106
- pkt = g_queue_pop_head(&conn->primary_list);
101
+ xpc_dictionary_set_string(if_desc,
107
+ pkt = g_queue_pop_tail(&conn->primary_list);
102
+ vmnet_start_address_key,
108
compare_chr_send(s,
103
+ options->start_address);
109
pkt->data,
104
+ xpc_dictionary_set_string(if_desc,
110
pkt->size,
105
+ vmnet_end_address_key,
111
@@ -XXX,XX +XXX,XX @@ static void colo_flush_packets(void *opaque, void *user_data)
106
+ options->end_address);
112
packet_destroy_partial(pkt, NULL);
107
+ xpc_dictionary_set_string(if_desc,
113
}
108
+ vmnet_subnet_mask_key,
114
while (!g_queue_is_empty(&conn->secondary_list)) {
109
+ options->subnet_mask);
115
- pkt = g_queue_pop_head(&conn->secondary_list);
110
+ }
116
+ pkt = g_queue_pop_tail(&conn->secondary_list);
111
+
117
packet_destroy(pkt, NULL);
112
+ return if_desc;
118
}
113
+}
114
+
115
+static NetClientInfo net_vmnet_host_info = {
116
+ .type = NET_CLIENT_DRIVER_VMNET_HOST,
117
+ .size = sizeof(VmnetState),
118
+ .receive = vmnet_receive_common,
119
+ .cleanup = vmnet_cleanup_common,
120
+};
121
+
122
int net_init_vmnet_host(const Netdev *netdev, const char *name,
123
- NetClientState *peer, Error **errp) {
124
- error_setg(errp, "vmnet-host is not implemented yet");
125
- return -1;
126
+ NetClientState *peer, Error **errp)
127
+{
128
+ NetClientState *nc = qemu_new_net_client(&net_vmnet_host_info,
129
+ peer, "vmnet-host", name);
130
+ xpc_object_t if_desc;
131
+ int result = -1;
132
+
133
+ if (!validate_options(netdev, errp)) {
134
+ return result;
135
+ }
136
+
137
+ if_desc = build_if_desc(netdev);
138
+ result = vmnet_if_create(nc, if_desc, errp);
139
+ xpc_release(if_desc);
140
+ return result;
119
}
141
}
120
--
142
--
121
2.7.4
143
2.25.1
122
123
diff view generated by jsdifflib
1
From: Rao Lei <lei.rao@intel.com>
1
From: Vladislav Yaroshchuk <vladislav.yaroshchuk@jetbrains.com>
2
2
3
This patch is to improve the logic of QEMU main thread sleep code in
3
Reviewed-by: Akihiko Odaki <akihiko.odaki@gmail.com>
4
qemu_chr_write_buffer() where it can be blocked and can't run other
4
Tested-by: Akihiko Odaki <akihiko.odaki@gmail.com>
5
coroutines during COLO IO stress test.
5
Signed-off-by: Vladislav Yaroshchuk <Vladislav.Yaroshchuk@jetbrains.com>
6
7
Our approach is to put filter_send() in a coroutine. In this way,
8
filter_send() will call qemu_coroutine_yield() in qemu_co_sleep_ns(),
9
so that it can be scheduled out and QEMU main thread has opportunity to
10
run other tasks.
11
12
Signed-off-by: Lei Rao <lei.rao@intel.com>
13
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
14
Reviewed-by: Li Zhijian <lizhijian@fujitsu.com>
15
Reviewed-by: Zhang Chen <chen.zhang@intel.com>
16
Signed-off-by: Jason Wang <jasowang@redhat.com>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
17
---
7
---
18
net/filter-mirror.c | 66 ++++++++++++++++++++++++++++++++++++++++++-----------
8
net/vmnet-bridged.m | 137 ++++++++++++++++++++++++++++++++++++++++++--
19
1 file changed, 53 insertions(+), 13 deletions(-)
9
1 file changed, 132 insertions(+), 5 deletions(-)
20
10
21
diff --git a/net/filter-mirror.c b/net/filter-mirror.c
11
diff --git a/net/vmnet-bridged.m b/net/vmnet-bridged.m
22
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
23
--- a/net/filter-mirror.c
13
--- a/net/vmnet-bridged.m
24
+++ b/net/filter-mirror.c
14
+++ b/net/vmnet-bridged.m
25
@@ -XXX,XX +XXX,XX @@
15
@@ -XXX,XX +XXX,XX @@
26
#include "chardev/char-fe.h"
16
27
#include "qemu/iov.h"
17
#include "qemu/osdep.h"
28
#include "qemu/sockets.h"
18
#include "qapi/qapi-types-net.h"
29
+#include "block/aio-wait.h"
19
-#include "vmnet_int.h"
30
20
-#include "clients.h"
31
#define TYPE_FILTER_MIRROR "filter-mirror"
21
-#include "qemu/error-report.h"
32
typedef struct MirrorState MirrorState;
22
#include "qapi/error.h"
33
@@ -XXX,XX +XXX,XX @@ struct MirrorState {
23
+#include "clients.h"
34
bool vnet_hdr;
24
+#include "vmnet_int.h"
35
};
25
36
26
#include <vmnet/vmnet.h>
37
-static int filter_send(MirrorState *s,
27
38
- const struct iovec *iov,
39
- int iovcnt)
40
+typedef struct FilterSendCo {
41
+ MirrorState *s;
42
+ char *buf;
43
+ ssize_t size;
44
+ bool done;
45
+ int ret;
46
+} FilterSendCo;
47
+
28
+
48
+static int _filter_send(MirrorState *s,
29
+static bool validate_ifname(const char *ifname)
49
+ char *buf,
50
+ ssize_t size)
51
{
52
NetFilterState *nf = NETFILTER(s);
53
int ret = 0;
54
- ssize_t size = 0;
55
uint32_t len = 0;
56
- char *buf;
57
-
58
- size = iov_size(iov, iovcnt);
59
- if (!size) {
60
- return 0;
61
- }
62
63
len = htonl(size);
64
ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len));
65
@@ -XXX,XX +XXX,XX @@ static int filter_send(MirrorState *s,
66
}
67
}
68
69
- buf = g_malloc(size);
70
- iov_to_buf(iov, iovcnt, 0, buf, size);
71
ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)buf, size);
72
- g_free(buf);
73
if (ret != size) {
74
goto err;
75
}
76
@@ -XXX,XX +XXX,XX @@ err:
77
return ret < 0 ? ret : -EIO;
78
}
79
80
+static void coroutine_fn filter_send_co(void *opaque)
81
+{
30
+{
82
+ FilterSendCo *data = opaque;
31
+ xpc_object_t shared_if_list = vmnet_copy_shared_interface_list();
32
+ bool match = false;
33
+ if (!xpc_array_get_count(shared_if_list)) {
34
+ goto done;
35
+ }
83
+
36
+
84
+ data->ret = _filter_send(data->s, data->buf, data->size);
37
+ match = !xpc_array_apply(
85
+ data->done = true;
38
+ shared_if_list,
86
+ g_free(data->buf);
39
+ ^bool(size_t index, xpc_object_t value) {
87
+ aio_wait_kick();
40
+ return strcmp(xpc_string_get_string_ptr(value), ifname) != 0;
41
+ });
42
+
43
+done:
44
+ xpc_release(shared_if_list);
45
+ return match;
88
+}
46
+}
89
+
47
+
90
+static int filter_send(MirrorState *s,
48
+
91
+ const struct iovec *iov,
49
+static char* get_valid_ifnames()
92
+ int iovcnt)
93
+{
50
+{
94
+ ssize_t size = iov_size(iov, iovcnt);
51
+ xpc_object_t shared_if_list = vmnet_copy_shared_interface_list();
95
+ char *buf = NULL;
52
+ __block char *if_list = NULL;
53
+ __block char *if_list_prev = NULL;
96
+
54
+
97
+ if (!size) {
55
+ if (!xpc_array_get_count(shared_if_list)) {
98
+ return 0;
56
+ goto done;
99
+ }
57
+ }
100
+
58
+
101
+ buf = g_malloc(size);
59
+ xpc_array_apply(
102
+ iov_to_buf(iov, iovcnt, 0, buf, size);
60
+ shared_if_list,
61
+ ^bool(size_t index, xpc_object_t value) {
62
+ /* build list of strings like "en0 en1 en2 " */
63
+ if_list = g_strconcat(xpc_string_get_string_ptr(value),
64
+ " ",
65
+ if_list_prev,
66
+ NULL);
67
+ g_free(if_list_prev);
68
+ if_list_prev = if_list;
69
+ return true;
70
+ });
103
+
71
+
104
+ FilterSendCo data = {
72
+done:
105
+ .s = s,
73
+ xpc_release(shared_if_list);
106
+ .size = size,
74
+ return if_list;
107
+ .buf = buf,
75
+}
108
+ .ret = 0,
109
+ };
110
+
76
+
111
+ Coroutine *co = qemu_coroutine_create(filter_send_co, &data);
112
+ qemu_coroutine_enter(co);
113
+
77
+
114
+ while (!data.done) {
78
+static bool validate_options(const Netdev *netdev, Error **errp)
115
+ aio_poll(qemu_get_aio_context(), true);
79
+{
80
+ const NetdevVmnetBridgedOptions *options = &(netdev->u.vmnet_bridged);
81
+ char* if_list;
82
+
83
+ if (!validate_ifname(options->ifname)) {
84
+ if_list = get_valid_ifnames();
85
+ if (if_list) {
86
+ error_setg(errp,
87
+ "unsupported ifname '%s', expected one of [ %s]",
88
+ options->ifname,
89
+ if_list);
90
+ g_free(if_list);
91
+ } else {
92
+ error_setg(errp,
93
+ "unsupported ifname '%s', no supported "
94
+ "interfaces available",
95
+ options->ifname);
96
+ }
97
+ return false;
116
+ }
98
+ }
117
+
99
+
118
+ return data.ret;
100
+#if !defined(MAC_OS_VERSION_11_0) || \
101
+ MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_VERSION_11_0
102
+ if (options->has_isolated) {
103
+ error_setg(errp,
104
+ "vmnet-bridged.isolated feature is "
105
+ "unavailable: outdated vmnet.framework API");
106
+ return false;
107
+ }
108
+#endif
109
+ return true;
119
+}
110
+}
120
+
111
+
121
static void redirector_to_filter(NetFilterState *nf,
112
+
122
const uint8_t *buf,
113
+static xpc_object_t build_if_desc(const Netdev *netdev)
123
int len)
114
+{
115
+ const NetdevVmnetBridgedOptions *options = &(netdev->u.vmnet_bridged);
116
+ xpc_object_t if_desc = xpc_dictionary_create(NULL, NULL, 0);
117
+
118
+ xpc_dictionary_set_uint64(if_desc,
119
+ vmnet_operation_mode_key,
120
+ VMNET_BRIDGED_MODE
121
+ );
122
+
123
+ xpc_dictionary_set_string(if_desc,
124
+ vmnet_shared_interface_name_key,
125
+ options->ifname);
126
+
127
+#if defined(MAC_OS_VERSION_11_0) && \
128
+ MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_11_0
129
+ xpc_dictionary_set_bool(if_desc,
130
+ vmnet_enable_isolation_key,
131
+ options->isolated);
132
+#endif
133
+ return if_desc;
134
+}
135
+
136
+
137
+static NetClientInfo net_vmnet_bridged_info = {
138
+ .type = NET_CLIENT_DRIVER_VMNET_BRIDGED,
139
+ .size = sizeof(VmnetState),
140
+ .receive = vmnet_receive_common,
141
+ .cleanup = vmnet_cleanup_common,
142
+};
143
+
144
+
145
int net_init_vmnet_bridged(const Netdev *netdev, const char *name,
146
NetClientState *peer, Error **errp)
147
{
148
- error_setg(errp, "vmnet-bridged is not implemented yet");
149
- return -1;
150
+ NetClientState *nc = qemu_new_net_client(&net_vmnet_bridged_info,
151
+ peer, "vmnet-bridged", name);
152
+ xpc_object_t if_desc;
153
+ int result = -1;
154
+
155
+ if (!validate_options(netdev, errp)) {
156
+ return result;
157
+ }
158
+
159
+ if_desc = build_if_desc(netdev);
160
+ result = vmnet_if_create(nc, if_desc, errp);
161
+ xpc_release(if_desc);
162
+ return result;
163
}
124
--
164
--
125
2.7.4
165
2.25.1
126
127
diff view generated by jsdifflib
1
From: Peter Foley <pefoley@google.com>
1
From: Vladislav Yaroshchuk <vladislav.yaroshchuk@jetbrains.com>
2
2
3
e.g.
3
Update qemu-options.hx to support vmnet networking backend.
4
1109 15:16:20.151506 Uninitialized bytes in ioctl_common_pre at offset 0 inside [0x7ffc516af9b8, 4)
5
1109 15:16:20.151659 ==588974==WARNING: MemorySanitizer: use-of-uninitialized-value
6
1109 15:16:20.312923 #0 0x5639b88acb21 in tap_probe_vnet_hdr_len third_party/qemu/net/tap-linux.c:183:9
7
1109 15:16:20.312952 #1 0x5639b88afd66 in net_tap_fd_init third_party/qemu/net/tap.c:409:9
8
1109 15:16:20.312954 #2 0x5639b88b2d1b in net_init_tap_one third_party/qemu/net/tap.c:681:19
9
1109 15:16:20.312956 #3 0x5639b88b16a8 in net_init_tap third_party/qemu/net/tap.c:912:13
10
1109 15:16:20.312957 #4 0x5639b8890175 in net_client_init1 third_party/qemu/net/net.c:1110:9
11
1109 15:16:20.312958 #5 0x5639b888f912 in net_client_init third_party/qemu/net/net.c:1208:15
12
1109 15:16:20.312960 #6 0x5639b8894aa5 in net_param_nic third_party/qemu/net/net.c:1588:11
13
1109 15:16:20.312961 #7 0x5639b900cd18 in qemu_opts_foreach third_party/qemu/util/qemu-option.c:1135:14
14
1109 15:16:20.312962 #8 0x5639b889393c in net_init_clients third_party/qemu/net/net.c:1612:9
15
1109 15:16:20.312964 #9 0x5639b717aaf3 in qemu_create_late_backends third_party/qemu/softmmu/vl.c:1962:5
16
1109 15:16:20.312965 #10 0x5639b717aaf3 in qemu_init third_party/qemu/softmmu/vl.c:3694:5
17
1109 15:16:20.312967 #11 0x5639b71083b8 in main third_party/qemu/softmmu/main.c:49:5
18
1109 15:16:20.312968 #12 0x7f464de1d8d2 in __libc_start_main (/usr/grte/v5/lib64/libc.so.6+0x628d2)
19
1109 15:16:20.312969 #13 0x5639b6bbd389 in _start /usr/grte/v5/debug-src/src/csu/../sysdeps/x86_64/start.S:120
20
1109 15:16:20.312970
21
1109 15:16:20.312975 Uninitialized value was stored to memory at
22
1109 15:16:20.313393 #0 0x5639b88acbee in tap_probe_vnet_hdr_len third_party/qemu/net/tap-linux.c
23
1109 15:16:20.313396 #1 0x5639b88afd66 in net_tap_fd_init third_party/qemu/net/tap.c:409:9
24
1109 15:16:20.313398 #2 0x5639b88b2d1b in net_init_tap_one third_party/qemu/net/tap.c:681:19
25
1109 15:16:20.313399 #3 0x5639b88b16a8 in net_init_tap third_party/qemu/net/tap.c:912:13
26
1109 15:16:20.313400 #4 0x5639b8890175 in net_client_init1 third_party/qemu/net/net.c:1110:9
27
1109 15:16:20.313401 #5 0x5639b888f912 in net_client_init third_party/qemu/net/net.c:1208:15
28
1109 15:16:20.313403 #6 0x5639b8894aa5 in net_param_nic third_party/qemu/net/net.c:1588:11
29
1109 15:16:20.313404 #7 0x5639b900cd18 in qemu_opts_foreach third_party/qemu/util/qemu-option.c:1135:14
30
1109 15:16:20.313405 #8 0x5639b889393c in net_init_clients third_party/qemu/net/net.c:1612:9
31
1109 15:16:20.313407 #9 0x5639b717aaf3 in qemu_create_late_backends third_party/qemu/softmmu/vl.c:1962:5
32
1109 15:16:20.313408 #10 0x5639b717aaf3 in qemu_init third_party/qemu/softmmu/vl.c:3694:5
33
1109 15:16:20.313409 #11 0x5639b71083b8 in main third_party/qemu/softmmu/main.c:49:5
34
1109 15:16:20.313410 #12 0x7f464de1d8d2 in __libc_start_main (/usr/grte/v5/lib64/libc.so.6+0x628d2)
35
1109 15:16:20.313412 #13 0x5639b6bbd389 in _start /usr/grte/v5/debug-src/src/csu/../sysdeps/x86_64/start.S:120
36
1109 15:16:20.313413
37
1109 15:16:20.313417 Uninitialized value was stored to memory at
38
1109 15:16:20.313791 #0 0x5639b88affbd in net_tap_fd_init third_party/qemu/net/tap.c:400:26
39
1109 15:16:20.313826 #1 0x5639b88b2d1b in net_init_tap_one third_party/qemu/net/tap.c:681:19
40
1109 15:16:20.313829 #2 0x5639b88b16a8 in net_init_tap third_party/qemu/net/tap.c:912:13
41
1109 15:16:20.313831 #3 0x5639b8890175 in net_client_init1 third_party/qemu/net/net.c:1110:9
42
1109 15:16:20.313836 #4 0x5639b888f912 in net_client_init third_party/qemu/net/net.c:1208:15
43
1109 15:16:20.313838 #5 0x5639b8894aa5 in net_param_nic third_party/qemu/net/net.c:1588:11
44
1109 15:16:20.313839 #6 0x5639b900cd18 in qemu_opts_foreach third_party/qemu/util/qemu-option.c:1135:14
45
1109 15:16:20.313841 #7 0x5639b889393c in net_init_clients third_party/qemu/net/net.c:1612:9
46
1109 15:16:20.313843 #8 0x5639b717aaf3 in qemu_create_late_backends third_party/qemu/softmmu/vl.c:1962:5
47
1109 15:16:20.313844 #9 0x5639b717aaf3 in qemu_init third_party/qemu/softmmu/vl.c:3694:5
48
1109 15:16:20.313845 #10 0x5639b71083b8 in main third_party/qemu/softmmu/main.c:49:5
49
1109 15:16:20.313846 #11 0x7f464de1d8d2 in __libc_start_main (/usr/grte/v5/lib64/libc.so.6+0x628d2)
50
1109 15:16:20.313847 #12 0x5639b6bbd389 in _start /usr/grte/v5/debug-src/src/csu/../sysdeps/x86_64/start.S:120
51
1109 15:16:20.313849
52
1109 15:16:20.313851 Uninitialized value was created by an allocation of 'ifr' in the stack frame of function 'tap_probe_vnet_hdr'
53
1109 15:16:20.313855 #0 0x5639b88ac680 in tap_probe_vnet_hdr third_party/qemu/net/tap-linux.c:151
54
1109 15:16:20.313856
55
1109 15:16:20.313878 SUMMARY: MemorySanitizer: use-of-uninitialized-value third_party/qemu/net/tap-linux.c:183:9 in tap_probe_vnet_hdr_len
56
4
57
Fixes: dc69004c7d8 ("net: move tap_probe_vnet_hdr() to tap-linux.c")
5
Reviewed-by: Akihiko Odaki <akihiko.odaki@gmail.com>
58
Reviewed-by: Hao Wu <wuhaotsh@google.com>
6
Tested-by: Akihiko Odaki <akihiko.odaki@gmail.com>
59
Reviewed-by: Patrick Venture <venture@google.com>
7
Signed-off-by: Vladislav Yaroshchuk <Vladislav.Yaroshchuk@jetbrains.com>
60
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
61
Signed-off-by: Peter Foley <pefoley@google.com>
62
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
63
---
9
---
64
net/tap-linux.c | 1 +
10
qemu-options.hx | 25 +++++++++++++++++++++++++
65
1 file changed, 1 insertion(+)
11
1 file changed, 25 insertions(+)
66
12
67
diff --git a/net/tap-linux.c b/net/tap-linux.c
13
diff --git a/qemu-options.hx b/qemu-options.hx
68
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
69
--- a/net/tap-linux.c
15
--- a/qemu-options.hx
70
+++ b/net/tap-linux.c
16
+++ b/qemu-options.hx
71
@@ -XXX,XX +XXX,XX @@ void tap_set_sndbuf(int fd, const NetdevTapOptions *tap, Error **errp)
17
@@ -XXX,XX +XXX,XX @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
72
int tap_probe_vnet_hdr(int fd, Error **errp)
18
#ifdef __linux__
73
{
19
"-netdev vhost-vdpa,id=str,vhostdev=/path/to/dev\n"
74
struct ifreq ifr;
20
" configure a vhost-vdpa network,Establish a vhost-vdpa netdev\n"
75
+ memset(&ifr, 0, sizeof(ifr));
21
+#endif
76
22
+#ifdef CONFIG_VMNET
77
if (ioctl(fd, TUNGETIFF, &ifr) != 0) {
23
+ "-netdev vmnet-host,id=str[,isolated=on|off][,net-uuid=uuid]\n"
78
/* TUNGETIFF is available since kernel v2.6.27 */
24
+ " [,start-address=addr,end-address=addr,subnet-mask=mask]\n"
25
+ " configure a vmnet network backend in host mode with ID 'str',\n"
26
+ " isolate this interface from others with 'isolated',\n"
27
+ " configure the address range and choose a subnet mask,\n"
28
+ " specify network UUID 'uuid' to disable DHCP and interact with\n"
29
+ " vmnet-host interfaces within this isolated network\n"
30
+ "-netdev vmnet-shared,id=str[,isolated=on|off][,nat66-prefix=addr]\n"
31
+ " [,start-address=addr,end-address=addr,subnet-mask=mask]\n"
32
+ " configure a vmnet network backend in shared mode with ID 'str',\n"
33
+ " configure the address range and choose a subnet mask,\n"
34
+ " set IPv6 ULA prefix (of length 64) to use for internal network,\n"
35
+ " isolate this interface from others with 'isolated'\n"
36
+ "-netdev vmnet-bridged,id=str,ifname=name[,isolated=on|off]\n"
37
+ " configure a vmnet network backend in bridged mode with ID 'str',\n"
38
+ " use 'ifname=name' to select a physical network interface to be bridged,\n"
39
+ " isolate this interface from others with 'isolated'\n"
40
#endif
41
"-netdev hubport,id=str,hubid=n[,netdev=nd]\n"
42
" configure a hub port on the hub with ID 'n'\n", QEMU_ARCH_ALL)
43
@@ -XXX,XX +XXX,XX @@ DEF("nic", HAS_ARG, QEMU_OPTION_nic,
44
#endif
45
#ifdef CONFIG_POSIX
46
"vhost-user|"
47
+#endif
48
+#ifdef CONFIG_VMNET
49
+ "vmnet-host|vmnet-shared|vmnet-bridged|"
50
#endif
51
"socket][,option][,...][mac=macaddr]\n"
52
" initialize an on-board / default host NIC (using MAC address\n"
53
@@ -XXX,XX +XXX,XX @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
54
#endif
55
#ifdef CONFIG_NETMAP
56
"netmap|"
57
+#endif
58
+#ifdef CONFIG_VMNET
59
+ "vmnet-host|vmnet-shared|vmnet-bridged|"
60
#endif
61
"socket][,option][,option][,...]\n"
62
" old way to initialize a host network interface\n"
79
--
63
--
80
2.7.4
64
2.25.1
81
82
diff view generated by jsdifflib
1
From: Peter Foley <pefoley@google.com>
1
From: Vladislav Yaroshchuk <vladislav.yaroshchuk@jetbrains.com>
2
2
3
Match the other error handling in this function.
3
Update HMP for supporting vmnet.
4
4
5
Fixes: e7b347d0bf6 ("net: detect errors from probing vnet hdr flag for TAP devices")
5
Reviewed-by: Akihiko Odaki <akihiko.odaki@gmail.com>
6
6
Tested-by: Akihiko Odaki <akihiko.odaki@gmail.com>
7
Reviewed-by: Patrick Venture <venture@google.com>
7
Signed-off-by: Vladislav Yaroshchuk <Vladislav.Yaroshchuk@jetbrains.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Signed-off-by: Peter Foley <pefoley@google.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
---
9
---
12
net/tap.c | 1 +
10
hmp-commands.hx | 6 +++++-
13
1 file changed, 1 insertion(+)
11
1 file changed, 5 insertions(+), 1 deletion(-)
14
12
15
diff --git a/net/tap.c b/net/tap.c
13
diff --git a/hmp-commands.hx b/hmp-commands.hx
16
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
17
--- a/net/tap.c
15
--- a/hmp-commands.hx
18
+++ b/net/tap.c
16
+++ b/hmp-commands.hx
19
@@ -XXX,XX +XXX,XX @@ int net_init_tap(const Netdev *netdev, const char *name,
17
@@ -XXX,XX +XXX,XX @@ ERST
20
if (i == 0) {
18
{
21
vnet_hdr = tap_probe_vnet_hdr(fd, errp);
19
.name = "netdev_add",
22
if (vnet_hdr < 0) {
20
.args_type = "netdev:O",
23
+ ret = -1;
21
- .params = "[user|tap|socket|vde|bridge|hubport|netmap|vhost-user],id=str[,prop=value][,...]",
24
goto free_fail;
22
+ .params = "[user|tap|socket|vde|bridge|hubport|netmap|vhost-user"
25
}
23
+#ifdef CONFIG_VMNET
26
} else if (vnet_hdr != tap_probe_vnet_hdr(fd, NULL)) {
24
+ "|vmnet-host|vmnet-shared|vmnet-bridged"
25
+#endif
26
+ "],id=str[,prop=value][,...]",
27
.help = "add host network device",
28
.cmd = hmp_netdev_add,
29
.command_completion = netdev_add_completion,
27
--
30
--
28
2.7.4
31
2.25.1
29
30
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Helge Deller <deller@gmx.de>
2
2
3
The "Interrupt Cause" register (VMXNET3_REG_ICR) is read-only.
3
The MAC of the tulip card is stored in the EEPROM and at startup
4
Write accesses are ignored. Log them with as LOG_GUEST_ERROR
4
tulip_fill_eeprom() is called to initialize the EEPROM with the MAC
5
instead of aborting:
5
address given on the command line, e.g.:
6
-device tulip,mac=00:11:22:33:44:55
6
7
7
[R +0.239743] writeq 0xe0002031 0x46291a5a55460800
8
In case the mac address was not given on the command line,
8
ERROR:hw/net/vmxnet3.c:1819:vmxnet3_io_bar1_write: code should not be reached
9
tulip_fill_eeprom() initializes the MAC in EEPROM with 00:00:00:00:00:00
9
Thread 1 "qemu-system-i38" received signal SIGABRT, Aborted.
10
which breaks e.g. a HP-UX guest.
10
(gdb) bt
11
#3 0x74c397d3 in __GI_abort () at abort.c:79
12
#4 0x76d3cd4c in g_assertion_message (domain=<optimized out>, file=<optimized out>, line=<optimized out>, func=<optimized out>, message=<optimized out>) at ../glib/gtestutils.c:3223
13
#5 0x76d9d45f in g_assertion_message_expr
14
(domain=0x0, file=0x59fc2e53 "hw/net/vmxnet3.c", line=1819, func=0x59fc11e0 <__func__.vmxnet3_io_bar1_write> "vmxnet3_io_bar1_write", expr=<optimized out>)
15
at ../glib/gtestutils.c:3249
16
#6 0x57e80a3a in vmxnet3_io_bar1_write (opaque=0x62814100, addr=56, val=70, size=4) at hw/net/vmxnet3.c:1819
17
#7 0x58c2d894 in memory_region_write_accessor (mr=0x62816b90, addr=56, value=0x7fff9450, size=4, shift=0, mask=4294967295, attrs=...) at softmmu/memory.c:492
18
#8 0x58c2d1d2 in access_with_adjusted_size (addr=56, value=0x7fff9450, size=1, access_size_min=4, access_size_max=4, access_fn=
19
0x58c2d290 <memory_region_write_accessor>, mr=0x62816b90, attrs=...) at softmmu/memory.c:554
20
#9 0x58c2bae7 in memory_region_dispatch_write (mr=0x62816b90, addr=56, data=70, op=MO_8, attrs=...) at softmmu/memory.c:1504
21
#10 0x58bfd034 in flatview_write_continue (fv=0x606000181700, addr=0xe0002038, attrs=..., ptr=0x7fffb9e0, len=1, addr1=56, l=1, mr=0x62816b90)
22
at softmmu/physmem.c:2782
23
#11 0x58beba00 in flatview_write (fv=0x606000181700, addr=0xe0002031, attrs=..., buf=0x7fffb9e0, len=8) at softmmu/physmem.c:2822
24
#12 0x58beb589 in address_space_write (as=0x608000015f20, addr=0xe0002031, attrs=..., buf=0x7fffb9e0, len=8) at softmmu/physmem.c:2914
25
11
26
Reported-by: Dike <dike199774@qq.com>
12
Fix this problem by moving qemu_macaddr_default_if_unset() a few lines
27
Reported-by: Duhao <504224090@qq.com>
13
up, so that a default mac address is assigned before tulip_fill_eeprom()
28
BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=2032932
14
initializes the EEPROM.
29
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
15
16
Signed-off-by: Helge Deller <deller@gmx.de>
17
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
30
Signed-off-by: Jason Wang <jasowang@redhat.com>
18
Signed-off-by: Jason Wang <jasowang@redhat.com>
31
---
19
---
32
hw/net/vmxnet3.c | 4 +++-
20
hw/net/tulip.c | 4 ++--
33
1 file changed, 3 insertions(+), 1 deletion(-)
21
1 file changed, 2 insertions(+), 2 deletions(-)
34
22
35
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
23
diff --git a/hw/net/tulip.c b/hw/net/tulip.c
36
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/net/vmxnet3.c
25
--- a/hw/net/tulip.c
38
+++ b/hw/net/vmxnet3.c
26
+++ b/hw/net/tulip.c
39
@@ -XXX,XX +XXX,XX @@ vmxnet3_io_bar1_write(void *opaque,
27
@@ -XXX,XX +XXX,XX @@ static void pci_tulip_realize(PCIDevice *pci_dev, Error **errp)
40
case VMXNET3_REG_ICR:
28
pci_conf = s->dev.config;
41
VMW_CBPRN("Write BAR1 [VMXNET3_REG_ICR] = %" PRIx64 ", size %d",
29
pci_conf[PCI_INTERRUPT_PIN] = 1; /* interrupt pin A */
42
val, size);
30
43
- g_assert_not_reached();
31
+ qemu_macaddr_default_if_unset(&s->c.macaddr);
44
+ qemu_log_mask(LOG_GUEST_ERROR,
32
+
45
+ "%s: write to read-only register VMXNET3_REG_ICR\n",
33
s->eeprom = eeprom93xx_new(&pci_dev->qdev, 64);
46
+ TYPE_VMXNET3);
34
tulip_fill_eeprom(s);
47
break;
35
48
36
@@ -XXX,XX +XXX,XX @@ static void pci_tulip_realize(PCIDevice *pci_dev, Error **errp)
49
/* Event Cause Register */
37
38
s->irq = pci_allocate_irq(&s->dev);
39
40
- qemu_macaddr_default_if_unset(&s->c.macaddr);
41
-
42
s->nic = qemu_new_nic(&net_tulip_info, &s->c,
43
object_get_typename(OBJECT(pci_dev)),
44
pci_dev->qdev.id, s);
50
--
45
--
51
2.7.4
46
2.25.1
52
47
53
48
diff view generated by jsdifflib