1
The following changes since commit 23895cbd82be95428e90168b12e925d0d3ca2f06:
1
The following changes since commit 13356edb87506c148b163b8c7eb0695647d00c2a:
2
2
3
Merge remote-tracking branch 'remotes/awilliam/tags/vfio-update-20201123.0' into staging (2020-11-23 18:51:13 +0000)
3
Merge tag 'block-pull-request' of https://gitlab.com/stefanha/qemu into staging (2023-01-24 09:45:33 +0000)
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 9925990d01a92564af55f6f69d0f5f59b47609b1:
9
for you to fetch changes up to 2bd492bca521ee8594f1d5db8dc9aac126fc4f85:
10
10
11
net: Use correct default-path macro for downscript (2020-11-24 10:40:17 +0800)
11
vdpa: fix VHOST_BACKEND_F_IOTLB_ASID flag check (2023-02-02 14:16:48 +0800)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
14
15
----------------------------------------------------------------
15
----------------------------------------------------------------
16
Keqian Zhu (1):
16
Christian Svensson (1):
17
net: Use correct default-path macro for downscript
17
net: Increase L2TPv3 buffer to fit jumboframes
18
18
19
Paolo Bonzini (1):
19
Eugenio Pérez (1):
20
net: do not exit on "netdev_add help" monitor command
20
vdpa: fix VHOST_BACKEND_F_IOTLB_ASID flag check
21
21
22
Prasad J Pandit (1):
22
Fiona Ebner (1):
23
hw/net/e1000e: advance desc_offset in case of null descriptor
23
hw/net/vmxnet3: allow VMXNET3_MAX_MTU itself as a value
24
24
25
Yuri Benditovich (1):
25
Joelle van Dyne (1):
26
net: purge queued rx packets on queue deletion
26
vmnet: stop recieving events when VM is stopped
27
27
28
yuanjungong (1):
28
Laurent Vivier (2):
29
tap: fix a memory leak
29
tests/qtest: netdev: test stream and dgram backends
30
net: stream: add a new option to automatically reconnect
30
31
31
hw/net/e1000e_core.c | 8 +++---
32
Qiang Liu (2):
32
include/net/net.h | 1 +
33
hw/net/lan9118: log [read|write]b when mode_16bit is enabled rather than abort
33
monitor/hmp-cmds.c | 6 ++++
34
hw/net/can/xlnx-zynqmp-can: fix assertion failures in transfer_fifo()
34
net/net.c | 80 +++++++++++++++++++++++++++-------------------------
35
35
net/tap.c | 5 +++-
36
Thomas Huth (3):
36
5 files changed, 57 insertions(+), 43 deletions(-)
37
net: Move the code to collect available NIC models to a separate function
38
net: Restore printing of the help text with "-nic help"
39
net: Replace "Supported NIC models" with "Available NIC models"
40
41
hw/net/can/xlnx-zynqmp-can.c | 9 +-
42
hw/net/lan9118.c | 17 +-
43
hw/net/vmxnet3.c | 2 +-
44
hw/pci/pci.c | 29 +--
45
include/net/net.h | 14 ++
46
net/l2tpv3.c | 2 +-
47
net/net.c | 50 +++-
48
net/stream.c | 53 ++++-
49
net/vhost-vdpa.c | 2 +-
50
net/vmnet-common.m | 48 +++-
51
net/vmnet_int.h | 2 +
52
qapi/net.json | 7 +-
53
qemu-options.hx | 6 +-
54
tests/qtest/meson.build | 2 +
55
tests/qtest/netdev-socket.c | 549 +++++++++++++++++++++++++++++++++++++++++++
56
15 files changed, 730 insertions(+), 62 deletions(-)
57
create mode 100644 tests/qtest/netdev-socket.c
37
58
38
59
60
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
"netdev_add help" is causing QEMU to exit because the code that
3
The code that collects the available NIC models is not really specific
4
invokes show_netdevs is shared between CLI and HMP processing.
4
to PCI anymore and will be required in the next patch, too, so let's
5
Move the check to the callers so that exit(0) remains only
5
move this into a new separate function in net.c instead.
6
in the CLI flow.
7
6
8
"netdev_add help" is not fixed by this patch; that is left for
7
Signed-off-by: Thomas Huth <thuth@redhat.com>
9
later work.
10
11
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
---
9
---
14
include/net/net.h | 1 +
10
hw/pci/pci.c | 29 +----------------------------
15
monitor/hmp-cmds.c | 6 +++++
11
include/net/net.h | 14 ++++++++++++++
16
net/net.c | 68 +++++++++++++++++++++++++++---------------------------
12
net/net.c | 34 ++++++++++++++++++++++++++++++++++
17
3 files changed, 41 insertions(+), 34 deletions(-)
13
3 files changed, 49 insertions(+), 28 deletions(-)
18
14
15
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/pci/pci.c
18
+++ b/hw/pci/pci.c
19
@@ -XXX,XX +XXX,XX @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
20
const char *default_devaddr)
21
{
22
const char *devaddr = nd->devaddr ? nd->devaddr : default_devaddr;
23
- GSList *list;
24
GPtrArray *pci_nic_models;
25
PCIBus *bus;
26
PCIDevice *pci_dev;
27
@@ -XXX,XX +XXX,XX @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
28
nd->model = g_strdup("virtio-net-pci");
29
}
30
31
- list = object_class_get_list_sorted(TYPE_PCI_DEVICE, false);
32
- pci_nic_models = g_ptr_array_new();
33
- while (list) {
34
- DeviceClass *dc = OBJECT_CLASS_CHECK(DeviceClass, list->data,
35
- TYPE_DEVICE);
36
- GSList *next;
37
- if (test_bit(DEVICE_CATEGORY_NETWORK, dc->categories) &&
38
- dc->user_creatable) {
39
- const char *name = object_class_get_name(list->data);
40
- /*
41
- * A network device might also be something else than a NIC, see
42
- * e.g. the "rocker" device. Thus we have to look for the "netdev"
43
- * property, too. Unfortunately, some devices like virtio-net only
44
- * create this property during instance_init, so we have to create
45
- * a temporary instance here to be able to check it.
46
- */
47
- Object *obj = object_new_with_class(OBJECT_CLASS(dc));
48
- if (object_property_find(obj, "netdev")) {
49
- g_ptr_array_add(pci_nic_models, (gpointer)name);
50
- }
51
- object_unref(obj);
52
- }
53
- next = list->next;
54
- g_slist_free_1(list);
55
- list = next;
56
- }
57
- g_ptr_array_add(pci_nic_models, NULL);
58
+ pci_nic_models = qemu_get_nic_models(TYPE_PCI_DEVICE);
59
60
if (qemu_show_nic_models(nd->model, (const char **)pci_nic_models->pdata)) {
61
exit(0);
19
diff --git a/include/net/net.h b/include/net/net.h
62
diff --git a/include/net/net.h b/include/net/net.h
20
index XXXXXXX..XXXXXXX 100644
63
index XXXXXXX..XXXXXXX 100644
21
--- a/include/net/net.h
64
--- a/include/net/net.h
22
+++ b/include/net/net.h
65
+++ b/include/net/net.h
23
@@ -XXX,XX +XXX,XX @@ extern const char *host_net_devices[];
66
@@ -XXX,XX +XXX,XX @@ void net_socket_rs_init(SocketReadState *rs,
24
67
bool vnet_hdr);
25
/* from net.c */
68
NetClientState *qemu_get_peer(NetClientState *nc, int queue_index);
26
int net_client_parse(QemuOptsList *opts_list, const char *str);
69
27
+void show_netdevs(void);
70
+/**
28
int net_init_clients(Error **errp);
71
+ * qemu_get_nic_models:
29
void net_check_clients(void);
72
+ * @device_type: Defines which devices should be taken into consideration
30
void net_cleanup(void);
73
+ * (e.g. TYPE_DEVICE for all devices, or TYPE_PCI_DEVICE for PCI)
31
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
74
+ *
32
index XXXXXXX..XXXXXXX 100644
75
+ * Get an array of pointers to names of NIC devices that are available in
33
--- a/monitor/hmp-cmds.c
76
+ * the QEMU binary. The array is terminated with a NULL pointer entry.
34
+++ b/monitor/hmp-cmds.c
77
+ * The caller is responsible for freeing the memory when it is not required
35
@@ -XXX,XX +XXX,XX @@
78
+ * anymore, e.g. with g_ptr_array_free(..., true).
36
#include "qemu/option.h"
79
+ *
37
#include "qemu/timer.h"
80
+ * Returns: Pointer to the array that contains the pointers to the names.
38
#include "qemu/sockets.h"
81
+ */
39
+#include "qemu/help_option.h"
82
+GPtrArray *qemu_get_nic_models(const char *device_type);
40
#include "monitor/monitor-internal.h"
83
+
41
#include "qapi/error.h"
84
/* NIC info */
42
#include "qapi/clone-visitor.h"
85
43
@@ -XXX,XX +XXX,XX @@ void hmp_netdev_add(Monitor *mon, const QDict *qdict)
86
#define MAX_NICS 8
44
{
45
Error *err = NULL;
46
QemuOpts *opts;
47
+ const char *type = qdict_get_try_str(qdict, "type");
48
49
+ if (type && is_help_option(type)) {
50
+ show_netdevs();
51
+ return;
52
+ }
53
opts = qemu_opts_from_qdict(qemu_find_opts("netdev"), qdict, &err);
54
if (err) {
55
goto out;
56
diff --git a/net/net.c b/net/net.c
87
diff --git a/net/net.c b/net/net.c
57
index XXXXXXX..XXXXXXX 100644
88
index XXXXXXX..XXXXXXX 100644
58
--- a/net/net.c
89
--- a/net/net.c
59
+++ b/net/net.c
90
+++ b/net/net.c
60
@@ -XXX,XX +XXX,XX @@
91
@@ -XXX,XX +XXX,XX @@ static int nic_get_free_idx(void)
61
#include "qemu/config-file.h"
92
return -1;
62
#include "qemu/ctype.h"
63
#include "qemu/iov.h"
64
+#include "qemu/qemu-print.h"
65
#include "qemu/main-loop.h"
66
#include "qemu/option.h"
67
#include "qapi/error.h"
68
@@ -XXX,XX +XXX,XX @@ static int net_client_init1(const Netdev *netdev, bool is_netdev, Error **errp)
69
return 0;
70
}
93
}
71
94
72
-static void show_netdevs(void)
95
+GPtrArray *qemu_get_nic_models(const char *device_type)
73
+void show_netdevs(void)
96
+{
97
+ GPtrArray *nic_models = g_ptr_array_new();
98
+ GSList *list = object_class_get_list_sorted(device_type, false);
99
+
100
+ while (list) {
101
+ DeviceClass *dc = OBJECT_CLASS_CHECK(DeviceClass, list->data,
102
+ TYPE_DEVICE);
103
+ GSList *next;
104
+ if (test_bit(DEVICE_CATEGORY_NETWORK, dc->categories) &&
105
+ dc->user_creatable) {
106
+ const char *name = object_class_get_name(list->data);
107
+ /*
108
+ * A network device might also be something else than a NIC, see
109
+ * e.g. the "rocker" device. Thus we have to look for the "netdev"
110
+ * property, too. Unfortunately, some devices like virtio-net only
111
+ * create this property during instance_init, so we have to create
112
+ * a temporary instance here to be able to check it.
113
+ */
114
+ Object *obj = object_new_with_class(OBJECT_CLASS(dc));
115
+ if (object_property_find(obj, "netdev")) {
116
+ g_ptr_array_add(nic_models, (gpointer)name);
117
+ }
118
+ object_unref(obj);
119
+ }
120
+ next = list->next;
121
+ g_slist_free_1(list);
122
+ list = next;
123
+ }
124
+ g_ptr_array_add(nic_models, NULL);
125
+
126
+ return nic_models;
127
+}
128
+
129
int qemu_show_nic_models(const char *arg, const char *const *models)
74
{
130
{
75
int idx;
131
int i;
76
const char *available_netdevs[] = {
77
@@ -XXX,XX +XXX,XX @@ static void show_netdevs(void)
78
#endif
79
};
80
81
- printf("Available netdev backend types:\n");
82
+ qemu_printf("Available netdev backend types:\n");
83
for (idx = 0; idx < ARRAY_SIZE(available_netdevs); idx++) {
84
- puts(available_netdevs[idx]);
85
+ qemu_printf("%s\n", available_netdevs[idx]);
86
}
87
}
88
89
@@ -XXX,XX +XXX,XX @@ static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp)
90
int ret = -1;
91
Visitor *v = opts_visitor_new(opts);
92
93
- const char *type = qemu_opt_get(opts, "type");
94
-
95
- if (is_netdev && type && is_help_option(type)) {
96
- show_netdevs();
97
- exit(0);
98
- } else {
99
- /* Parse convenience option format ip6-net=fec0::0[/64] */
100
- const char *ip6_net = qemu_opt_get(opts, "ipv6-net");
101
+ /* Parse convenience option format ip6-net=fec0::0[/64] */
102
+ const char *ip6_net = qemu_opt_get(opts, "ipv6-net");
103
104
- if (ip6_net) {
105
- char *prefix_addr;
106
- unsigned long prefix_len = 64; /* Default 64bit prefix length. */
107
+ if (ip6_net) {
108
+ char *prefix_addr;
109
+ unsigned long prefix_len = 64; /* Default 64bit prefix length. */
110
111
- substrings = g_strsplit(ip6_net, "/", 2);
112
- if (!substrings || !substrings[0]) {
113
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "ipv6-net",
114
- "a valid IPv6 prefix");
115
- goto out;
116
- }
117
+ substrings = g_strsplit(ip6_net, "/", 2);
118
+ if (!substrings || !substrings[0]) {
119
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "ipv6-net",
120
+ "a valid IPv6 prefix");
121
+ goto out;
122
+ }
123
124
- prefix_addr = substrings[0];
125
+ prefix_addr = substrings[0];
126
127
- /* Handle user-specified prefix length. */
128
- if (substrings[1] &&
129
- qemu_strtoul(substrings[1], NULL, 10, &prefix_len))
130
- {
131
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
132
- "ipv6-prefixlen", "a number");
133
- goto out;
134
- }
135
-
136
- qemu_opt_set(opts, "ipv6-prefix", prefix_addr, &error_abort);
137
- qemu_opt_set_number(opts, "ipv6-prefixlen", prefix_len,
138
- &error_abort);
139
- qemu_opt_unset(opts, "ipv6-net");
140
+ /* Handle user-specified prefix length. */
141
+ if (substrings[1] &&
142
+ qemu_strtoul(substrings[1], NULL, 10, &prefix_len))
143
+ {
144
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
145
+ "ipv6-prefixlen", "a number");
146
+ goto out;
147
}
148
+
149
+ qemu_opt_set(opts, "ipv6-prefix", prefix_addr, &error_abort);
150
+ qemu_opt_set_number(opts, "ipv6-prefixlen", prefix_len,
151
+ &error_abort);
152
+ qemu_opt_unset(opts, "ipv6-net");
153
}
154
155
/* Create an ID for -net if the user did not specify one */
156
@@ -XXX,XX +XXX,XX @@ static int net_init_client(void *dummy, QemuOpts *opts, Error **errp)
157
158
static int net_init_netdev(void *dummy, QemuOpts *opts, Error **errp)
159
{
160
+ const char *type = qemu_opt_get(opts, "type");
161
+
162
+ if (type && is_help_option(type)) {
163
+ show_netdevs();
164
+ exit(0);
165
+ }
166
return net_client_init(opts, true, errp);
167
}
168
169
--
132
--
170
2.7.4
133
2.7.4
171
172
diff view generated by jsdifflib
1
From: Keqian Zhu <zhukeqian1@huawei.com>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
Fixes: 63c4db4c2e6d (net: relocate paths to helpers and scripts)
3
Running QEMU with "-nic help" used to work in QEMU 5.2 and earlier versions
4
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
4
(it showed the available netdev backends), but this feature got broken during
5
some refactoring in version 6.0. Let's restore the old behavior, and while
6
we're at it, let's also print the available NIC models here now since this
7
option can be used to configure both, netdev backend and model in one go.
8
9
Fixes: ad6f932fe8 ("net: do not exit on "netdev_add help" monitor command")
10
Signed-off-by: Thomas Huth <thuth@redhat.com>
5
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
6
---
12
---
7
net/tap.c | 3 ++-
13
net/net.c | 14 ++++++++++++--
8
1 file changed, 2 insertions(+), 1 deletion(-)
14
1 file changed, 12 insertions(+), 2 deletions(-)
9
15
10
diff --git a/net/tap.c b/net/tap.c
16
diff --git a/net/net.c b/net/net.c
11
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
12
--- a/net/tap.c
18
--- a/net/net.c
13
+++ b/net/tap.c
19
+++ b/net/net.c
14
@@ -XXX,XX +XXX,XX @@ free_fail:
20
@@ -XXX,XX +XXX,XX @@ static int net_param_nic(void *dummy, QemuOpts *opts, Error **errp)
15
script = default_script = get_relocated_path(DEFAULT_NETWORK_SCRIPT);
21
const char *type;
16
}
22
17
if (!downscript) {
23
type = qemu_opt_get(opts, "type");
18
- downscript = default_downscript = get_relocated_path(DEFAULT_NETWORK_SCRIPT);
24
- if (type && g_str_equal(type, "none")) {
19
+ downscript = default_downscript =
25
- return 0; /* Nothing to do, default_net is cleared in vl.c */
20
+ get_relocated_path(DEFAULT_NETWORK_DOWN_SCRIPT);
26
+ if (type) {
21
}
27
+ if (g_str_equal(type, "none")) {
22
28
+ return 0; /* Nothing to do, default_net is cleared in vl.c */
23
if (tap->has_ifname) {
29
+ }
30
+ if (is_help_option(type)) {
31
+ GPtrArray *nic_models = qemu_get_nic_models(TYPE_DEVICE);
32
+ show_netdevs();
33
+ printf("\n");
34
+ qemu_show_nic_models(type, (const char **)nic_models->pdata);
35
+ g_ptr_array_free(nic_models, true);
36
+ exit(0);
37
+ }
38
}
39
40
idx = nic_get_free_idx();
24
--
41
--
25
2.7.4
42
2.7.4
26
27
diff view generated by jsdifflib
1
From: Yuri Benditovich <yuri.benditovich@daynix.com>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
https://bugzilla.redhat.com/show_bug.cgi?id=1829272
3
Just because a NIC model is compiled into the QEMU binary does not
4
When deleting queue pair, purge pending RX packets if any.
4
necessary mean that it can be used with each and every machine.
5
Example of problematic flow:
5
So let's rather talk about "available" models instead of "supported"
6
1. Bring up q35 VM with tap (vhost off) and virtio-net or e1000e
6
models, just to avoid confusion.
7
2. Run ping flood to the VM NIC ( 1 ms interval)
8
3. Hot unplug the NIC device (device_del)
9
During unplug process one or more packets come, the NIC
10
can't receive, tap disables read_poll
11
4. Hot plug the device (device_add) with the same netdev
12
The tap stays with read_poll disabled and does not receive
13
any packets anymore (tap_send never triggered)
14
7
15
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
8
Reviewed-by: Claudio Fontana <cfontana@suse.de>
9
Signed-off-by: Thomas Huth <thuth@redhat.com>
16
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
17
---
11
---
18
net/net.c | 12 ++++++++----
12
net/net.c | 2 +-
19
1 file changed, 8 insertions(+), 4 deletions(-)
13
1 file changed, 1 insertion(+), 1 deletion(-)
20
14
21
diff --git a/net/net.c b/net/net.c
15
diff --git a/net/net.c b/net/net.c
22
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
23
--- a/net/net.c
17
--- a/net/net.c
24
+++ b/net/net.c
18
+++ b/net/net.c
25
@@ -XXX,XX +XXX,XX @@ void qemu_del_nic(NICState *nic)
19
@@ -XXX,XX +XXX,XX @@ int qemu_show_nic_models(const char *arg, const char *const *models)
26
20
return 0;
27
qemu_macaddr_set_free(&nic->conf->macaddr);
28
29
- /* If this is a peer NIC and peer has already been deleted, free it now. */
30
- if (nic->peer_deleted) {
31
- for (i = 0; i < queues; i++) {
32
- qemu_free_net_client(qemu_get_subqueue(nic, i)->peer);
33
+ for (i = 0; i < queues; i++) {
34
+ NetClientState *nc = qemu_get_subqueue(nic, i);
35
+ /* If this is a peer NIC and peer has already been deleted, free it now. */
36
+ if (nic->peer_deleted) {
37
+ qemu_free_net_client(nc->peer);
38
+ } else if (nc->peer) {
39
+ /* if there are RX packets pending, complete them */
40
+ qemu_purge_queued_packets(nc->peer);
41
}
42
}
21
}
43
22
23
- printf("Supported NIC models:\n");
24
+ printf("Available NIC models:\n");
25
for (i = 0 ; models[i]; i++) {
26
printf("%s\n", models[i]);
27
}
44
--
28
--
45
2.7.4
29
2.7.4
46
47
diff view generated by jsdifflib
1
From: yuanjungong <ruc_gongyuanjun@163.com>
1
From: Qiang Liu <cyruscyliu@gmail.com>
2
2
3
Close fd before returning.
3
This patch replaces hw_error to guest error log for [read|write]b
4
accesses when mode_16bit is enabled. This avoids aborting qemu.
4
5
5
Buglink: https://bugs.launchpad.net/qemu/+bug/1904486
6
Fixes: 1248f8d4cbc3 ("hw/lan9118: Add basic 16-bit mode support.")
6
7
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1433
7
Signed-off-by: yuanjungong <ruc_gongyuanjun@163.com>
8
Reported-by: Qiang Liu <cyruscyliu@gmail.com>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Signed-off-by: Qiang Liu <cyruscyliu@gmail.com>
11
Suggested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
13
---
11
net/tap.c | 2 ++
14
hw/net/lan9118.c | 17 ++++++++---------
12
1 file changed, 2 insertions(+)
15
1 file changed, 8 insertions(+), 9 deletions(-)
13
16
14
diff --git a/net/tap.c b/net/tap.c
17
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/net/tap.c
19
--- a/hw/net/lan9118.c
17
+++ b/net/tap.c
20
+++ b/hw/net/lan9118.c
18
@@ -XXX,XX +XXX,XX @@ int net_init_tap(const Netdev *netdev, const char *name,
21
@@ -XXX,XX +XXX,XX @@
19
if (ret < 0) {
22
#include "migration/vmstate.h"
20
error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d",
23
#include "net/net.h"
21
name, fd);
24
#include "net/eth.h"
22
+ close(fd);
25
-#include "hw/hw.h"
23
return -1;
26
#include "hw/irq.h"
24
}
27
#include "hw/net/lan9118.h"
25
28
#include "hw/ptimer.h"
26
@@ -XXX,XX +XXX,XX @@ int net_init_tap(const Netdev *netdev, const char *name,
29
@@ -XXX,XX +XXX,XX @@
27
vhostfdname, vnet_hdr, fd, &err);
30
#ifdef DEBUG_LAN9118
28
if (err) {
31
#define DPRINTF(fmt, ...) \
29
error_propagate(errp, err);
32
do { printf("lan9118: " fmt , ## __VA_ARGS__); } while (0)
30
+ close(fd);
33
-#define BADF(fmt, ...) \
31
return -1;
34
-do { hw_error("lan9118: error: " fmt , ## __VA_ARGS__);} while (0)
32
}
35
#else
33
} else if (tap->has_fds) {
36
#define DPRINTF(fmt, ...) do {} while(0)
37
-#define BADF(fmt, ...) \
38
-do { fprintf(stderr, "lan9118: error: " fmt , ## __VA_ARGS__);} while (0)
39
#endif
40
41
/* The tx and rx fifo ports are a range of aliased 32-bit registers */
42
@@ -XXX,XX +XXX,XX @@ static uint32_t do_phy_read(lan9118_state *s, int reg)
43
case 30: /* Interrupt mask */
44
return s->phy_int_mask;
45
default:
46
- BADF("PHY read reg %d\n", reg);
47
+ qemu_log_mask(LOG_GUEST_ERROR,
48
+ "do_phy_read: PHY read reg %d\n", reg);
49
return 0;
50
}
51
}
52
@@ -XXX,XX +XXX,XX @@ static void do_phy_write(lan9118_state *s, int reg, uint32_t val)
53
phy_update_irq(s);
54
break;
55
default:
56
- BADF("PHY write reg %d = 0x%04x\n", reg, val);
57
+ qemu_log_mask(LOG_GUEST_ERROR,
58
+ "do_phy_write: PHY write reg %d = 0x%04x\n", reg, val);
59
}
60
}
61
62
@@ -XXX,XX +XXX,XX @@ static void lan9118_16bit_mode_write(void *opaque, hwaddr offset,
63
return;
64
}
65
66
- hw_error("lan9118_write: Bad size 0x%x\n", size);
67
+ qemu_log_mask(LOG_GUEST_ERROR,
68
+ "lan9118_16bit_mode_write: Bad size 0x%x\n", size);
69
}
70
71
static uint64_t lan9118_readl(void *opaque, hwaddr offset,
72
@@ -XXX,XX +XXX,XX @@ static uint64_t lan9118_16bit_mode_read(void *opaque, hwaddr offset,
73
return lan9118_readl(opaque, offset, size);
74
}
75
76
- hw_error("lan9118_read: Bad size 0x%x\n", size);
77
+ qemu_log_mask(LOG_GUEST_ERROR,
78
+ "lan9118_16bit_mode_read: Bad size 0x%x\n", size);
79
return 0;
80
}
81
34
--
82
--
35
2.7.4
83
2.7.4
36
84
37
85
diff view generated by jsdifflib
New patch
1
From: Fiona Ebner <f.ebner@proxmox.com>
1
2
3
Currently, VMXNET3_MAX_MTU itself (being 9000) is not considered a
4
valid value for the MTU, but a guest running ESXi 7.0 might try to
5
set it and fail the assert [0].
6
7
In the Linux kernel, dev->max_mtu itself is a valid value for the MTU
8
and for the vmxnet3 driver it's 9000, so a guest running Linux will
9
also fail the assert when trying to set an MTU of 9000.
10
11
VMXNET3_MAX_MTU and s->mtu don't seem to be used in relation to buffer
12
allocations/accesses, so allowing the upper limit itself as a value
13
should be fine.
14
15
[0]: https://forum.proxmox.com/threads/114011/
16
17
Fixes: d05dcd94ae ("net: vmxnet3: validate configuration values during activate (CVE-2021-20203)")
18
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
19
Signed-off-by: Jason Wang <jasowang@redhat.com>
20
---
21
hw/net/vmxnet3.c | 2 +-
22
1 file changed, 1 insertion(+), 1 deletion(-)
23
24
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/net/vmxnet3.c
27
+++ b/hw/net/vmxnet3.c
28
@@ -XXX,XX +XXX,XX @@ static void vmxnet3_activate_device(VMXNET3State *s)
29
vmxnet3_setup_rx_filtering(s);
30
/* Cache fields from shared memory */
31
s->mtu = VMXNET3_READ_DRV_SHARED32(d, s->drv_shmem, devRead.misc.mtu);
32
- assert(VMXNET3_MIN_MTU <= s->mtu && s->mtu < VMXNET3_MAX_MTU);
33
+ assert(VMXNET3_MIN_MTU <= s->mtu && s->mtu <= VMXNET3_MAX_MTU);
34
VMW_CFPRN("MTU is %u", s->mtu);
35
36
s->max_rx_frags =
37
--
38
2.7.4
diff view generated by jsdifflib
New patch
1
From: Christian Svensson <blue@cmd.nu>
1
2
3
Increase the allocated buffer size to fit larger packets.
4
Given that jumboframes can commonly be up to 9000 bytes the closest suitable
5
value seems to be 16 KiB.
6
7
Tested by running qemu towards a Linux L2TPv3 endpoint and pushing
8
jumboframe traffic through the interfaces.
9
10
Signed-off-by: Christian Svensson <blue@cmd.nu>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
13
net/l2tpv3.c | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
diff --git a/net/l2tpv3.c b/net/l2tpv3.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/net/l2tpv3.c
19
+++ b/net/l2tpv3.c
20
@@ -XXX,XX +XXX,XX @@
21
*/
22
23
#define BUFFER_ALIGN sysconf(_SC_PAGESIZE)
24
-#define BUFFER_SIZE 2048
25
+#define BUFFER_SIZE 16384
26
#define IOVSIZE 2
27
#define MAX_L2TPV3_MSGCNT 64
28
#define MAX_L2TPV3_IOVCNT (MAX_L2TPV3_MSGCNT * IOVSIZE)
29
--
30
2.7.4
diff view generated by jsdifflib
New patch
1
From: Joelle van Dyne <j@getutm.app>
1
2
3
When the VM is stopped using the HMP command "stop", soon the handler will
4
stop reading from the vmnet interface. This causes a flood of
5
`VMNET_INTERFACE_PACKETS_AVAILABLE` events to arrive and puts the host CPU
6
at 100%. We fix this by removing the event handler from vmnet when the VM
7
is no longer in a running state and restore it when we return to a running
8
state.
9
10
Signed-off-by: Joelle van Dyne <j@getutm.app>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
13
net/vmnet-common.m | 48 +++++++++++++++++++++++++++++++++++-------------
14
net/vmnet_int.h | 2 ++
15
2 files changed, 37 insertions(+), 13 deletions(-)
16
17
diff --git a/net/vmnet-common.m b/net/vmnet-common.m
18
index XXXXXXX..XXXXXXX 100644
19
--- a/net/vmnet-common.m
20
+++ b/net/vmnet-common.m
21
@@ -XXX,XX +XXX,XX @@
22
#include "clients.h"
23
#include "qemu/error-report.h"
24
#include "qapi/error.h"
25
+#include "sysemu/runstate.h"
26
27
#include <vmnet/vmnet.h>
28
#include <dispatch/dispatch.h>
29
@@ -XXX,XX +XXX,XX @@ static void vmnet_bufs_init(VmnetState *s)
30
}
31
}
32
33
+/**
34
+ * Called on state change to un-register/re-register handlers
35
+ */
36
+static void vmnet_vm_state_change_cb(void *opaque, bool running, RunState state)
37
+{
38
+ VmnetState *s = opaque;
39
+
40
+ if (running) {
41
+ vmnet_interface_set_event_callback(
42
+ s->vmnet_if,
43
+ VMNET_INTERFACE_PACKETS_AVAILABLE,
44
+ s->if_queue,
45
+ ^(interface_event_t event_id, xpc_object_t event) {
46
+ assert(event_id == VMNET_INTERFACE_PACKETS_AVAILABLE);
47
+ /*
48
+ * This function is being called from a non qemu thread, so
49
+ * we only schedule a BH, and do the rest of the io completion
50
+ * handling from vmnet_send_bh() which runs in a qemu context.
51
+ */
52
+ qemu_bh_schedule(s->send_bh);
53
+ });
54
+ } else {
55
+ vmnet_interface_set_event_callback(
56
+ s->vmnet_if,
57
+ VMNET_INTERFACE_PACKETS_AVAILABLE,
58
+ NULL,
59
+ NULL);
60
+ }
61
+}
62
63
int vmnet_if_create(NetClientState *nc,
64
xpc_object_t if_desc,
65
@@ -XXX,XX +XXX,XX @@ int vmnet_if_create(NetClientState *nc,
66
s->packets_send_current_pos = 0;
67
s->packets_send_end_pos = 0;
68
69
- vmnet_interface_set_event_callback(
70
- s->vmnet_if,
71
- VMNET_INTERFACE_PACKETS_AVAILABLE,
72
- s->if_queue,
73
- ^(interface_event_t event_id, xpc_object_t event) {
74
- assert(event_id == VMNET_INTERFACE_PACKETS_AVAILABLE);
75
- /*
76
- * This function is being called from a non qemu thread, so
77
- * we only schedule a BH, and do the rest of the io completion
78
- * handling from vmnet_send_bh() which runs in a qemu context.
79
- */
80
- qemu_bh_schedule(s->send_bh);
81
- });
82
+ vmnet_vm_state_change_cb(s, 1, RUN_STATE_RUNNING);
83
+
84
+ s->change = qemu_add_vm_change_state_handler(vmnet_vm_state_change_cb, s);
85
86
return 0;
87
}
88
@@ -XXX,XX +XXX,XX @@ void vmnet_cleanup_common(NetClientState *nc)
89
return;
90
}
91
92
+ vmnet_vm_state_change_cb(s, 0, RUN_STATE_SHUTDOWN);
93
+ qemu_del_vm_change_state_handler(s->change);
94
if_stopped_sem = dispatch_semaphore_create(0);
95
vmnet_stop_interface(
96
s->vmnet_if,
97
diff --git a/net/vmnet_int.h b/net/vmnet_int.h
98
index XXXXXXX..XXXXXXX 100644
99
--- a/net/vmnet_int.h
100
+++ b/net/vmnet_int.h
101
@@ -XXX,XX +XXX,XX @@ typedef struct VmnetState {
102
int packets_send_end_pos;
103
104
struct iovec iov_buf[VMNET_PACKETS_LIMIT];
105
+
106
+ VMChangeStateEntry *change;
107
} VmnetState;
108
109
const char *vmnet_status_map_str(vmnet_return_t status);
110
--
111
2.7.4
diff view generated by jsdifflib
New patch
1
From: Qiang Liu <cyruscyliu@gmail.com>
1
2
3
Check fifos before poping data from and pushing data into it.
4
5
Fixes: 98e5d7a2b726 ("hw/net/can: Introduce Xilinx ZynqMP CAN controller")
6
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1425
7
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1427
8
Reported-by: Qiang Liu <cyruscyliu@gmail.com>
9
Signed-off-by: Qiang Liu <cyruscyliu@gmail.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
---
12
hw/net/can/xlnx-zynqmp-can.c | 9 ++++++++-
13
1 file changed, 8 insertions(+), 1 deletion(-)
14
15
diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/net/can/xlnx-zynqmp-can.c
18
+++ b/hw/net/can/xlnx-zynqmp-can.c
19
@@ -XXX,XX +XXX,XX @@ static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo)
20
}
21
22
while (!fifo32_is_empty(fifo)) {
23
+ if (fifo32_num_used(fifo) < (4 * CAN_FRAME_SIZE)) {
24
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
25
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: data left in the fifo is not"
26
+ " enough for transfer.\n", path);
27
+ break;
28
+ }
29
for (i = 0; i < CAN_FRAME_SIZE; i++) {
30
data[i] = fifo32_pop(fifo);
31
}
32
@@ -XXX,XX +XXX,XX @@ static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo)
33
* acknowledged. The XlnxZynqMPCAN core receives any message
34
* that it transmits.
35
*/
36
- if (fifo32_is_full(&s->rx_fifo)) {
37
+ if (fifo32_is_full(&s->rx_fifo) ||
38
+ (fifo32_num_free(&s->rx_fifo) < (4 * CAN_FRAME_SIZE))) {
39
ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 1);
40
} else {
41
for (i = 0; i < CAN_FRAME_SIZE; i++) {
42
--
43
2.7.4
diff view generated by jsdifflib
New patch
1
From: Laurent Vivier <lvivier@redhat.com>
1
2
3
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
4
Acked-by: Michael S. Tsirkin <mst@redhat.com>
5
Acked-by: Thomas Huth <thuth@redhat.com>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
---
8
tests/qtest/meson.build | 2 +
9
tests/qtest/netdev-socket.c | 448 ++++++++++++++++++++++++++++++++++++++++++++
10
2 files changed, 450 insertions(+)
11
create mode 100644 tests/qtest/netdev-socket.c
12
13
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
14
index XXXXXXX..XXXXXXX 100644
15
--- a/tests/qtest/meson.build
16
+++ b/tests/qtest/meson.build
17
@@ -XXX,XX +XXX,XX @@ qtests_generic = [
18
'test-hmp',
19
'qos-test',
20
'readconfig-test',
21
+ 'netdev-socket',
22
]
23
if config_host.has_key('CONFIG_MODULES')
24
qtests_generic += [ 'modules-test' ]
25
@@ -XXX,XX +XXX,XX @@ qtests = {
26
'tpm-tis-device-swtpm-test': [io, tpmemu_files, 'tpm-tis-util.c'],
27
'tpm-tis-device-test': [io, tpmemu_files, 'tpm-tis-util.c'],
28
'vmgenid-test': files('boot-sector.c', 'acpi-utils.c'),
29
+ 'netdev-socket': files('netdev-socket.c', '../unit/socket-helpers.c'),
30
}
31
32
gvnc = dependency('gvnc-1.0', required: false)
33
diff --git a/tests/qtest/netdev-socket.c b/tests/qtest/netdev-socket.c
34
new file mode 100644
35
index XXXXXXX..XXXXXXX
36
--- /dev/null
37
+++ b/tests/qtest/netdev-socket.c
38
@@ -XXX,XX +XXX,XX @@
39
+/*
40
+ * QTest testcase for netdev stream and dgram
41
+ *
42
+ * Copyright (c) 2022 Red Hat, Inc.
43
+ *
44
+ * SPDX-License-Identifier: GPL-2.0-or-later
45
+ */
46
+
47
+#include "qemu/osdep.h"
48
+#include "qemu/sockets.h"
49
+#include <glib/gstdio.h>
50
+#include "../unit/socket-helpers.h"
51
+#include "libqtest.h"
52
+
53
+#define CONNECTION_TIMEOUT 5
54
+
55
+#define EXPECT_STATE(q, e, t) \
56
+do { \
57
+ char *resp = NULL; \
58
+ g_test_timer_start(); \
59
+ do { \
60
+ g_free(resp); \
61
+ resp = qtest_hmp(q, "info network"); \
62
+ if (t) { \
63
+ strrchr(resp, t)[0] = 0; \
64
+ } \
65
+ if (g_str_equal(resp, e)) { \
66
+ break; \
67
+ } \
68
+ } while (g_test_timer_elapsed() < CONNECTION_TIMEOUT); \
69
+ g_assert_cmpstr(resp, ==, e); \
70
+ g_free(resp); \
71
+} while (0)
72
+
73
+static gchar *tmpdir;
74
+
75
+static int inet_get_free_port_socket_ipv4(int sock)
76
+{
77
+ struct sockaddr_in addr;
78
+ socklen_t len;
79
+
80
+ memset(&addr, 0, sizeof(addr));
81
+ addr.sin_family = AF_INET;
82
+ addr.sin_addr.s_addr = INADDR_ANY;
83
+ addr.sin_port = 0;
84
+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
85
+ return -1;
86
+ }
87
+
88
+ len = sizeof(addr);
89
+ if (getsockname(sock, (struct sockaddr *)&addr, &len) < 0) {
90
+ return -1;
91
+ }
92
+
93
+ return ntohs(addr.sin_port);
94
+}
95
+
96
+static int inet_get_free_port_socket_ipv6(int sock)
97
+{
98
+ struct sockaddr_in6 addr;
99
+ socklen_t len;
100
+
101
+ memset(&addr, 0, sizeof(addr));
102
+ addr.sin6_family = AF_INET6;
103
+ addr.sin6_addr = in6addr_any;
104
+ addr.sin6_port = 0;
105
+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
106
+ return -1;
107
+ }
108
+
109
+ len = sizeof(addr);
110
+ if (getsockname(sock, (struct sockaddr *)&addr, &len) < 0) {
111
+ return -1;
112
+ }
113
+
114
+ return ntohs(addr.sin6_port);
115
+}
116
+
117
+static int inet_get_free_port_multiple(int nb, int *port, bool ipv6)
118
+{
119
+ int sock[nb];
120
+ int i;
121
+
122
+ for (i = 0; i < nb; i++) {
123
+ sock[i] = socket(ipv6 ? AF_INET6 : AF_INET, SOCK_STREAM, 0);
124
+ if (sock[i] < 0) {
125
+ break;
126
+ }
127
+ port[i] = ipv6 ? inet_get_free_port_socket_ipv6(sock[i]) :
128
+ inet_get_free_port_socket_ipv4(sock[i]);
129
+ if (port[i] == -1) {
130
+ break;
131
+ }
132
+ }
133
+
134
+ nb = i;
135
+ for (i = 0; i < nb; i++) {
136
+ closesocket(sock[i]);
137
+ }
138
+
139
+ return nb;
140
+}
141
+
142
+static int inet_get_free_port(bool ipv6)
143
+{
144
+ int nb, port;
145
+
146
+ nb = inet_get_free_port_multiple(1, &port, ipv6);
147
+ g_assert_cmpint(nb, ==, 1);
148
+
149
+ return port;
150
+}
151
+
152
+static void test_stream_inet_ipv4(void)
153
+{
154
+ QTestState *qts0, *qts1;
155
+ char *expect;
156
+ int port;
157
+
158
+ port = inet_get_free_port(false);
159
+ qts0 = qtest_initf("-nodefaults -M none "
160
+ "-netdev stream,id=st0,server=true,addr.type=inet,"
161
+ "addr.ipv4=on,addr.ipv6=off,"
162
+ "addr.host=127.0.0.1,addr.port=%d", port);
163
+
164
+ EXPECT_STATE(qts0, "st0: index=0,type=stream,\r\n", 0);
165
+
166
+ qts1 = qtest_initf("-nodefaults -M none "
167
+ "-netdev stream,server=false,id=st0,addr.type=inet,"
168
+ "addr.ipv4=on,addr.ipv6=off,"
169
+ "addr.host=127.0.0.1,addr.port=%d", port);
170
+
171
+ expect = g_strdup_printf("st0: index=0,type=stream,tcp:127.0.0.1:%d\r\n",
172
+ port);
173
+ EXPECT_STATE(qts1, expect, 0);
174
+ g_free(expect);
175
+
176
+ /* the port is unknown, check only the address */
177
+ EXPECT_STATE(qts0, "st0: index=0,type=stream,tcp:127.0.0.1", ':');
178
+
179
+ qtest_quit(qts1);
180
+ qtest_quit(qts0);
181
+}
182
+
183
+static void test_stream_inet_ipv6(void)
184
+{
185
+ QTestState *qts0, *qts1;
186
+ char *expect;
187
+ int port;
188
+
189
+ port = inet_get_free_port(true);
190
+ qts0 = qtest_initf("-nodefaults -M none "
191
+ "-netdev stream,id=st0,server=true,addr.type=inet,"
192
+ "addr.ipv4=off,addr.ipv6=on,"
193
+ "addr.host=::1,addr.port=%d", port);
194
+
195
+ EXPECT_STATE(qts0, "st0: index=0,type=stream,\r\n", 0);
196
+
197
+ qts1 = qtest_initf("-nodefaults -M none "
198
+ "-netdev stream,server=false,id=st0,addr.type=inet,"
199
+ "addr.ipv4=off,addr.ipv6=on,"
200
+ "addr.host=::1,addr.port=%d", port);
201
+
202
+ expect = g_strdup_printf("st0: index=0,type=stream,tcp:::1:%d\r\n",
203
+ port);
204
+ EXPECT_STATE(qts1, expect, 0);
205
+ g_free(expect);
206
+
207
+ /* the port is unknown, check only the address */
208
+ EXPECT_STATE(qts0, "st0: index=0,type=stream,tcp:::1", ':');
209
+
210
+ qtest_quit(qts1);
211
+ qtest_quit(qts0);
212
+}
213
+
214
+static void test_stream_unix(void)
215
+{
216
+ QTestState *qts0, *qts1;
217
+ char *expect;
218
+ gchar *path;
219
+
220
+ path = g_strconcat(tmpdir, "/stream_unix", NULL);
221
+
222
+ qts0 = qtest_initf("-nodefaults -M none "
223
+ "-netdev stream,id=st0,server=true,"
224
+ "addr.type=unix,addr.path=%s,",
225
+ path);
226
+
227
+ EXPECT_STATE(qts0, "st0: index=0,type=stream,\r\n", 0);
228
+
229
+ qts1 = qtest_initf("-nodefaults -M none "
230
+ "-netdev stream,id=st0,server=false,"
231
+ "addr.type=unix,addr.path=%s",
232
+ path);
233
+
234
+ expect = g_strdup_printf("st0: index=0,type=stream,unix:%s\r\n", path);
235
+ EXPECT_STATE(qts1, expect, 0);
236
+ EXPECT_STATE(qts0, expect, 0);
237
+ g_free(expect);
238
+ g_free(path);
239
+
240
+ qtest_quit(qts1);
241
+ qtest_quit(qts0);
242
+}
243
+
244
+#ifdef CONFIG_LINUX
245
+static void test_stream_unix_abstract(void)
246
+{
247
+ QTestState *qts0, *qts1;
248
+ char *expect;
249
+ gchar *path;
250
+
251
+ path = g_strconcat(tmpdir, "/stream_unix_abstract", NULL);
252
+
253
+ qts0 = qtest_initf("-nodefaults -M none "
254
+ "-netdev stream,id=st0,server=true,"
255
+ "addr.type=unix,addr.path=%s,"
256
+ "addr.abstract=on",
257
+ path);
258
+
259
+ EXPECT_STATE(qts0, "st0: index=0,type=stream,\r\n", 0);
260
+
261
+ qts1 = qtest_initf("-nodefaults -M none "
262
+ "-netdev stream,id=st0,server=false,"
263
+ "addr.type=unix,addr.path=%s,addr.abstract=on",
264
+ path);
265
+
266
+ expect = g_strdup_printf("st0: index=0,type=stream,unix:%s\r\n", path);
267
+ EXPECT_STATE(qts1, expect, 0);
268
+ EXPECT_STATE(qts0, expect, 0);
269
+ g_free(expect);
270
+ g_free(path);
271
+
272
+ qtest_quit(qts1);
273
+ qtest_quit(qts0);
274
+}
275
+#endif
276
+
277
+#ifndef _WIN32
278
+static void test_stream_fd(void)
279
+{
280
+ QTestState *qts0, *qts1;
281
+ int sock[2];
282
+ int ret;
283
+
284
+ ret = socketpair(AF_LOCAL, SOCK_STREAM, 0, sock);
285
+ g_assert_true(ret == 0);
286
+
287
+ qts0 = qtest_initf("-nodefaults -M none "
288
+ "-netdev stream,id=st0,addr.type=fd,addr.str=%d",
289
+ sock[0]);
290
+
291
+ EXPECT_STATE(qts0, "st0: index=0,type=stream,unix:\r\n", 0);
292
+
293
+ qts1 = qtest_initf("-nodefaults -M none "
294
+ "-netdev stream,id=st0,addr.type=fd,addr.str=%d",
295
+ sock[1]);
296
+
297
+ EXPECT_STATE(qts1, "st0: index=0,type=stream,unix:\r\n", 0);
298
+ EXPECT_STATE(qts0, "st0: index=0,type=stream,unix:\r\n", 0);
299
+
300
+ qtest_quit(qts1);
301
+ qtest_quit(qts0);
302
+
303
+ closesocket(sock[0]);
304
+ closesocket(sock[1]);
305
+}
306
+#endif
307
+
308
+static void test_dgram_inet(void)
309
+{
310
+ QTestState *qts0, *qts1;
311
+ char *expect;
312
+ int port[2];
313
+ int nb;
314
+
315
+ nb = inet_get_free_port_multiple(2, port, false);
316
+ g_assert_cmpint(nb, ==, 2);
317
+
318
+ qts0 = qtest_initf("-nodefaults -M none "
319
+ "-netdev dgram,id=st0,"
320
+ "local.type=inet,local.host=127.0.0.1,local.port=%d,"
321
+ "remote.type=inet,remote.host=127.0.0.1,remote.port=%d",
322
+ port[0], port[1]);
323
+
324
+ expect = g_strdup_printf("st0: index=0,type=dgram,"
325
+ "udp=127.0.0.1:%d/127.0.0.1:%d\r\n",
326
+ port[0], port[1]);
327
+ EXPECT_STATE(qts0, expect, 0);
328
+ g_free(expect);
329
+
330
+ qts1 = qtest_initf("-nodefaults -M none "
331
+ "-netdev dgram,id=st0,"
332
+ "local.type=inet,local.host=127.0.0.1,local.port=%d,"
333
+ "remote.type=inet,remote.host=127.0.0.1,remote.port=%d",
334
+ port[1], port[0]);
335
+
336
+ expect = g_strdup_printf("st0: index=0,type=dgram,"
337
+ "udp=127.0.0.1:%d/127.0.0.1:%d\r\n",
338
+ port[1], port[0]);
339
+ EXPECT_STATE(qts1, expect, 0);
340
+ g_free(expect);
341
+
342
+ qtest_quit(qts1);
343
+ qtest_quit(qts0);
344
+}
345
+
346
+#ifndef _WIN32
347
+static void test_dgram_mcast(void)
348
+{
349
+ QTestState *qts;
350
+
351
+ qts = qtest_initf("-nodefaults -M none "
352
+ "-netdev dgram,id=st0,"
353
+ "remote.type=inet,remote.host=230.0.0.1,remote.port=1234");
354
+
355
+ EXPECT_STATE(qts, "st0: index=0,type=dgram,mcast=230.0.0.1:1234\r\n", 0);
356
+
357
+ qtest_quit(qts);
358
+}
359
+
360
+static void test_dgram_unix(void)
361
+{
362
+ QTestState *qts0, *qts1;
363
+ char *expect;
364
+ gchar *path0, *path1;
365
+
366
+ path0 = g_strconcat(tmpdir, "/dgram_unix0", NULL);
367
+ path1 = g_strconcat(tmpdir, "/dgram_unix1", NULL);
368
+
369
+ qts0 = qtest_initf("-nodefaults -M none "
370
+ "-netdev dgram,id=st0,local.type=unix,local.path=%s,"
371
+ "remote.type=unix,remote.path=%s",
372
+ path0, path1);
373
+
374
+ expect = g_strdup_printf("st0: index=0,type=dgram,udp=%s:%s\r\n",
375
+ path0, path1);
376
+ EXPECT_STATE(qts0, expect, 0);
377
+ g_free(expect);
378
+
379
+ qts1 = qtest_initf("-nodefaults -M none "
380
+ "-netdev dgram,id=st0,local.type=unix,local.path=%s,"
381
+ "remote.type=unix,remote.path=%s",
382
+ path1, path0);
383
+
384
+
385
+ expect = g_strdup_printf("st0: index=0,type=dgram,udp=%s:%s\r\n",
386
+ path1, path0);
387
+ EXPECT_STATE(qts1, expect, 0);
388
+ g_free(expect);
389
+
390
+ unlink(path0);
391
+ g_free(path0);
392
+ unlink(path1);
393
+ g_free(path1);
394
+
395
+ qtest_quit(qts1);
396
+ qtest_quit(qts0);
397
+}
398
+
399
+static void test_dgram_fd(void)
400
+{
401
+ QTestState *qts0, *qts1;
402
+ char *expect;
403
+ int ret;
404
+ int sv[2];
405
+
406
+ ret = socketpair(PF_UNIX, SOCK_DGRAM, 0, sv);
407
+ g_assert_cmpint(ret, !=, -1);
408
+
409
+ qts0 = qtest_initf("-nodefaults -M none "
410
+ "-netdev dgram,id=st0,local.type=fd,local.str=%d",
411
+ sv[0]);
412
+
413
+ expect = g_strdup_printf("st0: index=0,type=dgram,fd=%d unix\r\n", sv[0]);
414
+ EXPECT_STATE(qts0, expect, 0);
415
+ g_free(expect);
416
+
417
+ qts1 = qtest_initf("-nodefaults -M none "
418
+ "-netdev dgram,id=st0,local.type=fd,local.str=%d",
419
+ sv[1]);
420
+
421
+
422
+ expect = g_strdup_printf("st0: index=0,type=dgram,fd=%d unix\r\n", sv[1]);
423
+ EXPECT_STATE(qts1, expect, 0);
424
+ g_free(expect);
425
+
426
+ qtest_quit(qts1);
427
+ qtest_quit(qts0);
428
+
429
+ closesocket(sv[0]);
430
+ closesocket(sv[1]);
431
+}
432
+#endif
433
+
434
+int main(int argc, char **argv)
435
+{
436
+ int ret;
437
+ bool has_ipv4, has_ipv6, has_afunix;
438
+ g_autoptr(GError) err = NULL;
439
+
440
+ socket_init();
441
+ g_test_init(&argc, &argv, NULL);
442
+
443
+ if (socket_check_protocol_support(&has_ipv4, &has_ipv6) < 0) {
444
+ g_error("socket_check_protocol_support() failed\n");
445
+ }
446
+
447
+ tmpdir = g_dir_make_tmp("netdev-socket.XXXXXX", &err);
448
+ if (tmpdir == NULL) {
449
+ g_error("Can't create temporary directory in %s: %s",
450
+ g_get_tmp_dir(), err->message);
451
+ }
452
+
453
+ if (has_ipv4) {
454
+ qtest_add_func("/netdev/stream/inet/ipv4", test_stream_inet_ipv4);
455
+ qtest_add_func("/netdev/dgram/inet", test_dgram_inet);
456
+#ifndef _WIN32
457
+ qtest_add_func("/netdev/dgram/mcast", test_dgram_mcast);
458
+#endif
459
+ }
460
+ if (has_ipv6) {
461
+ qtest_add_func("/netdev/stream/inet/ipv6", test_stream_inet_ipv6);
462
+ }
463
+
464
+ socket_check_afunix_support(&has_afunix);
465
+ if (has_afunix) {
466
+#ifndef _WIN32
467
+ qtest_add_func("/netdev/dgram/unix", test_dgram_unix);
468
+#endif
469
+ qtest_add_func("/netdev/stream/unix", test_stream_unix);
470
+#ifdef CONFIG_LINUX
471
+ qtest_add_func("/netdev/stream/unix/abstract",
472
+ test_stream_unix_abstract);
473
+#endif
474
+#ifndef _WIN32
475
+ qtest_add_func("/netdev/stream/fd", test_stream_fd);
476
+ qtest_add_func("/netdev/dgram/fd", test_dgram_fd);
477
+#endif
478
+ }
479
+
480
+ ret = g_test_run();
481
+
482
+ g_rmdir(tmpdir);
483
+ g_free(tmpdir);
484
+
485
+ return ret;
486
+}
487
--
488
2.7.4
diff view generated by jsdifflib
New patch
1
1
From: Laurent Vivier <lvivier@redhat.com>
2
3
In stream mode, if the server shuts down there is currently
4
no way to reconnect the client to a new server without removing
5
the NIC device and the netdev backend (or to reboot).
6
7
This patch introduces a reconnect option that specifies a delay
8
to try to reconnect with the same parameters.
9
10
Add a new test in qtest to test the reconnect option and the
11
connect/disconnect events.
12
13
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
14
Signed-off-by: Jason Wang <jasowang@redhat.com>
15
---
16
net/stream.c | 53 ++++++++++++++++++++++-
17
qapi/net.json | 7 ++-
18
qemu-options.hx | 6 +--
19
tests/qtest/netdev-socket.c | 101 ++++++++++++++++++++++++++++++++++++++++++++
20
4 files changed, 162 insertions(+), 5 deletions(-)
21
22
diff --git a/net/stream.c b/net/stream.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/net/stream.c
25
+++ b/net/stream.c
26
@@ -XXX,XX +XXX,XX @@
27
#include "io/channel-socket.h"
28
#include "io/net-listener.h"
29
#include "qapi/qapi-events-net.h"
30
+#include "qapi/qapi-visit-sockets.h"
31
+#include "qapi/clone-visitor.h"
32
33
typedef struct NetStreamState {
34
NetClientState nc;
35
@@ -XXX,XX +XXX,XX @@ typedef struct NetStreamState {
36
guint ioc_write_tag;
37
SocketReadState rs;
38
unsigned int send_index; /* number of bytes sent*/
39
+ uint32_t reconnect;
40
+ guint timer_tag;
41
+ SocketAddress *addr;
42
} NetStreamState;
43
44
static void net_stream_listen(QIONetListener *listener,
45
QIOChannelSocket *cioc,
46
void *opaque);
47
+static void net_stream_arm_reconnect(NetStreamState *s);
48
49
static gboolean net_stream_writable(QIOChannel *ioc,
50
GIOCondition condition,
51
@@ -XXX,XX +XXX,XX @@ static gboolean net_stream_send(QIOChannel *ioc,
52
qemu_set_info_str(&s->nc, "%s", "");
53
54
qapi_event_send_netdev_stream_disconnected(s->nc.name);
55
+ net_stream_arm_reconnect(s);
56
57
return G_SOURCE_REMOVE;
58
}
59
@@ -XXX,XX +XXX,XX @@ static gboolean net_stream_send(QIOChannel *ioc,
60
static void net_stream_cleanup(NetClientState *nc)
61
{
62
NetStreamState *s = DO_UPCAST(NetStreamState, nc, nc);
63
+ if (s->timer_tag) {
64
+ g_source_remove(s->timer_tag);
65
+ s->timer_tag = 0;
66
+ }
67
+ if (s->addr) {
68
+ qapi_free_SocketAddress(s->addr);
69
+ s->addr = NULL;
70
+ }
71
if (s->ioc) {
72
if (QIO_CHANNEL_SOCKET(s->ioc)->fd != -1) {
73
if (s->ioc_read_tag) {
74
@@ -XXX,XX +XXX,XX @@ static void net_stream_client_connected(QIOTask *task, gpointer opaque)
75
error:
76
object_unref(OBJECT(s->ioc));
77
s->ioc = NULL;
78
+ net_stream_arm_reconnect(s);
79
+}
80
+
81
+static gboolean net_stream_reconnect(gpointer data)
82
+{
83
+ NetStreamState *s = data;
84
+ QIOChannelSocket *sioc;
85
+
86
+ s->timer_tag = 0;
87
+
88
+ sioc = qio_channel_socket_new();
89
+ s->ioc = QIO_CHANNEL(sioc);
90
+ qio_channel_socket_connect_async(sioc, s->addr,
91
+ net_stream_client_connected, s,
92
+ NULL, NULL);
93
+ return G_SOURCE_REMOVE;
94
+}
95
+
96
+static void net_stream_arm_reconnect(NetStreamState *s)
97
+{
98
+ if (s->reconnect && s->timer_tag == 0) {
99
+ s->timer_tag = g_timeout_add_seconds(s->reconnect,
100
+ net_stream_reconnect, s);
101
+ }
102
}
103
104
static int net_stream_client_init(NetClientState *peer,
105
const char *model,
106
const char *name,
107
SocketAddress *addr,
108
+ uint32_t reconnect,
109
Error **errp)
110
{
111
NetStreamState *s;
112
@@ -XXX,XX +XXX,XX @@ static int net_stream_client_init(NetClientState *peer,
113
s->ioc = QIO_CHANNEL(sioc);
114
s->nc.link_down = true;
115
116
+ s->reconnect = reconnect;
117
+ if (reconnect) {
118
+ s->addr = QAPI_CLONE(SocketAddress, addr);
119
+ }
120
qio_channel_socket_connect_async(sioc, addr,
121
net_stream_client_connected, s,
122
NULL, NULL);
123
@@ -XXX,XX +XXX,XX @@ int net_init_stream(const Netdev *netdev, const char *name,
124
sock = &netdev->u.stream;
125
126
if (!sock->has_server || !sock->server) {
127
- return net_stream_client_init(peer, "stream", name, sock->addr, errp);
128
+ return net_stream_client_init(peer, "stream", name, sock->addr,
129
+ sock->has_reconnect ? sock->reconnect : 0,
130
+ errp);
131
+ }
132
+ if (sock->has_reconnect) {
133
+ error_setg(errp, "'reconnect' option is incompatible with "
134
+ "socket in server mode");
135
+ return -1;
136
}
137
return net_stream_server_init(peer, "stream", name, sock->addr, errp);
138
}
139
diff --git a/qapi/net.json b/qapi/net.json
140
index XXXXXXX..XXXXXXX 100644
141
--- a/qapi/net.json
142
+++ b/qapi/net.json
143
@@ -XXX,XX +XXX,XX @@
144
# @addr: socket address to listen on (server=true)
145
# or connect to (server=false)
146
# @server: create server socket (default: false)
147
+# @reconnect: For a client socket, if a socket is disconnected,
148
+# then attempt a reconnect after the given number of seconds.
149
+# Setting this to zero disables this function. (default: 0)
150
+# (since 8.0)
151
#
152
# Only SocketAddress types 'unix', 'inet' and 'fd' are supported.
153
#
154
@@ -XXX,XX +XXX,XX @@
155
{ 'struct': 'NetdevStreamOptions',
156
'data': {
157
'addr': 'SocketAddress',
158
- '*server': 'bool' } }
159
+ '*server': 'bool',
160
+ '*reconnect': 'uint32' } }
161
162
##
163
# @NetdevDgramOptions:
164
diff --git a/qemu-options.hx b/qemu-options.hx
165
index XXXXXXX..XXXXXXX 100644
166
--- a/qemu-options.hx
167
+++ b/qemu-options.hx
168
@@ -XXX,XX +XXX,XX @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
169
"-netdev socket,id=str[,fd=h][,udp=host:port][,localaddr=host:port]\n"
170
" configure a network backend to connect to another network\n"
171
" using an UDP tunnel\n"
172
- "-netdev stream,id=str[,server=on|off],addr.type=inet,addr.host=host,addr.port=port[,to=maxport][,numeric=on|off][,keep-alive=on|off][,mptcp=on|off][,addr.ipv4=on|off][,addr.ipv6=on|off]\n"
173
- "-netdev stream,id=str[,server=on|off],addr.type=unix,addr.path=path[,abstract=on|off][,tight=on|off]\n"
174
- "-netdev stream,id=str[,server=on|off],addr.type=fd,addr.str=file-descriptor\n"
175
+ "-netdev stream,id=str[,server=on|off],addr.type=inet,addr.host=host,addr.port=port[,to=maxport][,numeric=on|off][,keep-alive=on|off][,mptcp=on|off][,addr.ipv4=on|off][,addr.ipv6=on|off][,reconnect=seconds]\n"
176
+ "-netdev stream,id=str[,server=on|off],addr.type=unix,addr.path=path[,abstract=on|off][,tight=on|off][,reconnect=seconds]\n"
177
+ "-netdev stream,id=str[,server=on|off],addr.type=fd,addr.str=file-descriptor[,reconnect=seconds]\n"
178
" configure a network backend to connect to another network\n"
179
" using a socket connection in stream mode.\n"
180
"-netdev dgram,id=str,remote.type=inet,remote.host=maddr,remote.port=port[,local.type=inet,local.host=addr]\n"
181
diff --git a/tests/qtest/netdev-socket.c b/tests/qtest/netdev-socket.c
182
index XXXXXXX..XXXXXXX 100644
183
--- a/tests/qtest/netdev-socket.c
184
+++ b/tests/qtest/netdev-socket.c
185
@@ -XXX,XX +XXX,XX @@
186
#include <glib/gstdio.h>
187
#include "../unit/socket-helpers.h"
188
#include "libqtest.h"
189
+#include "qapi/qmp/qstring.h"
190
+#include "qemu/sockets.h"
191
+#include "qapi/qobject-input-visitor.h"
192
+#include "qapi/qapi-visit-sockets.h"
193
194
#define CONNECTION_TIMEOUT 5
195
196
@@ -XXX,XX +XXX,XX @@ static void test_stream_inet_ipv4(void)
197
qtest_quit(qts0);
198
}
199
200
+static void wait_stream_connected(QTestState *qts, const char *id,
201
+ SocketAddress **addr)
202
+{
203
+ QDict *resp, *data;
204
+ QString *qstr;
205
+ QObject *obj;
206
+ Visitor *v = NULL;
207
+
208
+ resp = qtest_qmp_eventwait_ref(qts, "NETDEV_STREAM_CONNECTED");
209
+ g_assert_nonnull(resp);
210
+ data = qdict_get_qdict(resp, "data");
211
+ g_assert_nonnull(data);
212
+
213
+ qstr = qobject_to(QString, qdict_get(data, "netdev-id"));
214
+ g_assert_nonnull(data);
215
+
216
+ g_assert(!strcmp(qstring_get_str(qstr), id));
217
+
218
+ obj = qdict_get(data, "addr");
219
+
220
+ v = qobject_input_visitor_new(obj);
221
+ visit_type_SocketAddress(v, NULL, addr, NULL);
222
+ visit_free(v);
223
+ qobject_unref(resp);
224
+}
225
+
226
+static void wait_stream_disconnected(QTestState *qts, const char *id)
227
+{
228
+ QDict *resp, *data;
229
+ QString *qstr;
230
+
231
+ resp = qtest_qmp_eventwait_ref(qts, "NETDEV_STREAM_DISCONNECTED");
232
+ g_assert_nonnull(resp);
233
+ data = qdict_get_qdict(resp, "data");
234
+ g_assert_nonnull(data);
235
+
236
+ qstr = qobject_to(QString, qdict_get(data, "netdev-id"));
237
+ g_assert_nonnull(data);
238
+
239
+ g_assert(!strcmp(qstring_get_str(qstr), id));
240
+ qobject_unref(resp);
241
+}
242
+
243
+static void test_stream_inet_reconnect(void)
244
+{
245
+ QTestState *qts0, *qts1;
246
+ int port;
247
+ SocketAddress *addr;
248
+
249
+ port = inet_get_free_port(false);
250
+ qts0 = qtest_initf("-nodefaults -M none "
251
+ "-netdev stream,id=st0,server=true,addr.type=inet,"
252
+ "addr.ipv4=on,addr.ipv6=off,"
253
+ "addr.host=127.0.0.1,addr.port=%d", port);
254
+
255
+ EXPECT_STATE(qts0, "st0: index=0,type=stream,\r\n", 0);
256
+
257
+ qts1 = qtest_initf("-nodefaults -M none "
258
+ "-netdev stream,server=false,id=st0,addr.type=inet,"
259
+ "addr.ipv4=on,addr.ipv6=off,reconnect=1,"
260
+ "addr.host=127.0.0.1,addr.port=%d", port);
261
+
262
+ wait_stream_connected(qts0, "st0", &addr);
263
+ g_assert_cmpint(addr->type, ==, SOCKET_ADDRESS_TYPE_INET);
264
+ g_assert_cmpstr(addr->u.inet.host, ==, "127.0.0.1");
265
+ qapi_free_SocketAddress(addr);
266
+
267
+ /* kill server */
268
+ qtest_quit(qts0);
269
+
270
+ /* check client has been disconnected */
271
+ wait_stream_disconnected(qts1, "st0");
272
+
273
+ /* restart server */
274
+ qts0 = qtest_initf("-nodefaults -M none "
275
+ "-netdev stream,id=st0,server=true,addr.type=inet,"
276
+ "addr.ipv4=on,addr.ipv6=off,"
277
+ "addr.host=127.0.0.1,addr.port=%d", port);
278
+
279
+ /* wait connection events*/
280
+ wait_stream_connected(qts0, "st0", &addr);
281
+ g_assert_cmpint(addr->type, ==, SOCKET_ADDRESS_TYPE_INET);
282
+ g_assert_cmpstr(addr->u.inet.host, ==, "127.0.0.1");
283
+ qapi_free_SocketAddress(addr);
284
+
285
+ wait_stream_connected(qts1, "st0", &addr);
286
+ g_assert_cmpint(addr->type, ==, SOCKET_ADDRESS_TYPE_INET);
287
+ g_assert_cmpstr(addr->u.inet.host, ==, "127.0.0.1");
288
+ g_assert_cmpint(atoi(addr->u.inet.port), ==, port);
289
+ qapi_free_SocketAddress(addr);
290
+
291
+ qtest_quit(qts1);
292
+ qtest_quit(qts0);
293
+}
294
+
295
static void test_stream_inet_ipv6(void)
296
{
297
QTestState *qts0, *qts1;
298
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
299
#ifndef _WIN32
300
qtest_add_func("/netdev/dgram/mcast", test_dgram_mcast);
301
#endif
302
+ qtest_add_func("/netdev/stream/inet/reconnect",
303
+ test_stream_inet_reconnect);
304
}
305
if (has_ipv6) {
306
qtest_add_func("/netdev/stream/inet/ipv6", test_stream_inet_ipv6);
307
--
308
2.7.4
diff view generated by jsdifflib
1
From: Prasad J Pandit <pjp@fedoraproject.org>
1
From: Eugenio Pérez <eperezma@redhat.com>
2
2
3
While receiving packets via e1000e_write_packet_to_guest() routine,
3
VHOST_BACKEND_F_IOTLB_ASID is the feature bit, not the bitmask. Since
4
'desc_offset' is advanced only when RX descriptor is processed. And
4
the device under test also provided VHOST_BACKEND_F_IOTLB_MSG_V2 and
5
RX descriptor is not processed if it has NULL buffer address.
5
VHOST_BACKEND_F_IOTLB_BATCH, this went unnoticed.
6
This may lead to an infinite loop condition. Increament 'desc_offset'
7
to process next descriptor in the ring to avoid infinite loop.
8
6
9
Reported-by: Cheol-woo Myung <330cjfdn@gmail.com>
7
Fixes: c1a1008685 ("vdpa: always start CVQ in SVQ mode if possible")
10
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
8
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
9
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
10
Acked-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
12
---
13
hw/net/e1000e_core.c | 8 ++++----
13
net/vhost-vdpa.c | 2 +-
14
1 file changed, 4 insertions(+), 4 deletions(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
15
16
diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
16
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/net/e1000e_core.c
18
--- a/net/vhost-vdpa.c
19
+++ b/hw/net/e1000e_core.c
19
+++ b/net/vhost-vdpa.c
20
@@ -XXX,XX +XXX,XX @@ e1000e_write_packet_to_guest(E1000ECore *core, struct NetRxPkt *pkt,
20
@@ -XXX,XX +XXX,XX @@ static int vhost_vdpa_net_cvq_start(NetClientState *nc)
21
(const char *) &fcs_pad, e1000x_fcs_len(core->mac));
21
g_strerror(errno), errno);
22
}
22
return -1;
23
}
23
}
24
- desc_offset += desc_size;
24
- if (!(backend_features & VHOST_BACKEND_F_IOTLB_ASID) ||
25
- if (desc_offset >= total_size) {
25
+ if (!(backend_features & BIT_ULL(VHOST_BACKEND_F_IOTLB_ASID)) ||
26
- is_last = true;
26
!vhost_vdpa_net_valid_svq_features(v->dev->features, NULL)) {
27
- }
27
return 0;
28
} else { /* as per intel docs; skip descriptors with null buf addr */
28
}
29
trace_e1000e_rx_null_descriptor();
30
}
31
+ desc_offset += desc_size;
32
+ if (desc_offset >= total_size) {
33
+ is_last = true;
34
+ }
35
36
e1000e_write_rx_descr(core, desc, is_last ? core->rx_pkt : NULL,
37
rss_info, do_ps ? ps_hdr_len : 0, &bastate.written);
38
--
29
--
39
2.7.4
30
2.7.4
40
31
41
32
diff view generated by jsdifflib