1
The following changes since commit 7d0e02405fc02a181319b1ab8681d2f72246b7c6:
1
The following changes since commit 13356edb87506c148b163b8c7eb0695647d00c2a:
2
2
3
Merge remote-tracking branch 'remotes/vivier2/tags/trivial-patches-pull-request' into staging (2019-07-01 17:40:32 +0100)
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 0e8818f023616677416840d6ddc880db8de3c967:
9
for you to fetch changes up to 2bd492bca521ee8594f1d5db8dc9aac126fc4f85:
10
10
11
migration/colo.c: Add missed filter notify for Xen COLO. (2019-07-02 10:21:07 +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
Cédric Le Goater (1):
16
Christian Svensson (1):
17
ftgmac100: do not link to netdev
17
net: Increase L2TPv3 buffer to fit jumboframes
18
18
19
Dr. David Alan Gilbert (5):
19
Eugenio Pérez (1):
20
net/announce: Allow optional list of interfaces
20
vdpa: fix VHOST_BACKEND_F_IOTLB_ASID flag check
21
net/announce: Add HMP optional interface list
22
net/announce: Add optional ID
23
net/announce: Add HMP optional ID
24
net/announce: Expand test for stopping self announce
25
21
26
Markus Armbruster (2):
22
Fiona Ebner (1):
27
MAINTAINERS: Add qemu-bridge-helper.c to "Network device backends"
23
hw/net/vmxnet3: allow VMXNET3_MAX_MTU itself as a value
28
qemu-bridge-helper: Document known shortcomings
29
24
30
Stefano Garzarella (4):
25
Joelle van Dyne (1):
31
net: fix assertion failure when ipv6-prefixlen is not a number
26
vmnet: stop recieving events when VM is stopped
32
net: avoid using variable length array in net_client_init()
33
net: use g_strsplit() for parsing host address and port
34
net: remove unused get_str_sep() function
35
27
36
Zhang Chen (5):
28
Laurent Vivier (2):
37
COLO-compare: Add new parameter to communicate with remote colo-frame
29
tests/qtest: netdev: test stream and dgram backends
38
COLO-compare: Add remote notification chardev handler frame
30
net: stream: add a new option to automatically reconnect
39
COLO-compare: Make the compare_chr_send() can send notification message.
40
COLO-compare: Add colo-compare remote notify support
41
migration/colo.c: Add missed filter notify for Xen COLO.
42
31
43
MAINTAINERS | 1 +
32
Qiang Liu (2):
44
hmp-commands.hx | 7 ++-
33
hw/net/lan9118: log [read|write]b when mode_16bit is enabled rather than abort
45
hw/net/ftgmac100.c | 2 -
34
hw/net/can/xlnx-zynqmp-can: fix assertion failures in transfer_fifo()
46
hw/net/virtio-net.c | 4 +-
35
47
include/net/announce.h | 8 ++-
36
Thomas Huth (3):
48
migration/colo.c | 2 +
37
net: Move the code to collect available NIC models to a separate function
49
monitor/hmp-cmds.c | 41 ++++++++++++-
38
net: Restore printing of the help text with "-nic help"
50
net/announce.c | 89 +++++++++++++++++++++++----
39
net: Replace "Supported NIC models" with "Available NIC models"
51
net/colo-compare.c | 155 ++++++++++++++++++++++++++++++++++++++++++------
40
52
net/net.c | 99 +++++++++++++++----------------
41
hw/net/can/xlnx-zynqmp-can.c | 9 +-
53
net/trace-events | 3 +-
42
hw/net/lan9118.c | 17 +-
54
qapi/net.json | 16 ++++-
43
hw/net/vmxnet3.c | 2 +-
55
qemu-bridge-helper.c | 12 +++-
44
hw/pci/pci.c | 29 +--
56
qemu-options.hx | 33 ++++++++++-
45
include/net/net.h | 14 ++
57
tests/virtio-net-test.c | 57 +++++++++++++++++-
46
net/l2tpv3.c | 2 +-
58
15 files changed, 430 insertions(+), 99 deletions(-)
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
59
58
60
59
60
diff view generated by jsdifflib
Deleted patch
1
From: Markus Armbruster <armbru@redhat.com>
2
1
3
Signed-off-by: Markus Armbruster <armbru@redhat.com>
4
Signed-off-by: Jason Wang <jasowang@redhat.com>
5
---
6
MAINTAINERS | 1 +
7
1 file changed, 1 insertion(+)
8
9
diff --git a/MAINTAINERS b/MAINTAINERS
10
index XXXXXXX..XXXXXXX 100644
11
--- a/MAINTAINERS
12
+++ b/MAINTAINERS
13
@@ -XXX,XX +XXX,XX @@ M: Jason Wang <jasowang@redhat.com>
14
S: Maintained
15
F: net/
16
F: include/net/
17
+F: qemu-bridge-helper.c
18
T: git https://github.com/jasowang/qemu.git net
19
F: qapi/net.json
20
21
--
22
2.5.0
23
24
diff view generated by jsdifflib
1
From: Stefano Garzarella <sgarzare@redhat.com>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
net_client_init() uses a variable length array to store the prefix
3
The code that collects the available NIC models is not really specific
4
of 'ipv6-net' parameter (e.g. if ipv6-net=fec0::0/64, the prefix
4
to PCI anymore and will be required in the next patch, too, so let's
5
is 'fec0::0').
5
move this into a new separate function in net.c instead.
6
This patch introduces g_strsplit() to split the 'ipv6-net' parameter,
7
so we can remove the variable length array.
8
6
9
Suggested-by: Markus Armbruster <armbru@redhat.com>
7
Signed-off-by: Thomas Huth <thuth@redhat.com>
10
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
11
Reviewed-by: Markus Armbruster <armbru@redhat.com>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
---
9
---
14
net/net.c | 31 +++++++++++++++++++------------
10
hw/pci/pci.c | 29 +----------------------------
15
1 file changed, 19 insertions(+), 12 deletions(-)
11
include/net/net.h | 14 ++++++++++++++
12
net/net.c | 34 ++++++++++++++++++++++++++++++++++
13
3 files changed, 49 insertions(+), 28 deletions(-)
16
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);
62
diff --git a/include/net/net.h b/include/net/net.h
63
index XXXXXXX..XXXXXXX 100644
64
--- a/include/net/net.h
65
+++ b/include/net/net.h
66
@@ -XXX,XX +XXX,XX @@ void net_socket_rs_init(SocketReadState *rs,
67
bool vnet_hdr);
68
NetClientState *qemu_get_peer(NetClientState *nc, int queue_index);
69
70
+/**
71
+ * qemu_get_nic_models:
72
+ * @device_type: Defines which devices should be taken into consideration
73
+ * (e.g. TYPE_DEVICE for all devices, or TYPE_PCI_DEVICE for PCI)
74
+ *
75
+ * Get an array of pointers to names of NIC devices that are available in
76
+ * the QEMU binary. The array is terminated with a NULL pointer entry.
77
+ * The caller is responsible for freeing the memory when it is not required
78
+ * anymore, e.g. with g_ptr_array_free(..., true).
79
+ *
80
+ * Returns: Pointer to the array that contains the pointers to the names.
81
+ */
82
+GPtrArray *qemu_get_nic_models(const char *device_type);
83
+
84
/* NIC info */
85
86
#define MAX_NICS 8
17
diff --git a/net/net.c b/net/net.c
87
diff --git a/net/net.c b/net/net.c
18
index XXXXXXX..XXXXXXX 100644
88
index XXXXXXX..XXXXXXX 100644
19
--- a/net/net.c
89
--- a/net/net.c
20
+++ b/net/net.c
90
+++ b/net/net.c
21
@@ -XXX,XX +XXX,XX @@ static void show_netdevs(void)
91
@@ -XXX,XX +XXX,XX @@ static int nic_get_free_idx(void)
22
92
return -1;
23
static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp)
93
}
94
95
+GPtrArray *qemu_get_nic_models(const char *device_type)
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)
24
{
130
{
25
+ gchar **substrings = NULL;
131
int i;
26
void *object = NULL;
27
Error *err = NULL;
28
int ret = -1;
29
@@ -XXX,XX +XXX,XX @@ static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp)
30
const char *ip6_net = qemu_opt_get(opts, "ipv6-net");
31
32
if (ip6_net) {
33
- char buf[strlen(ip6_net) + 1];
34
+ char *prefix_addr;
35
+ unsigned long prefix_len = 64; /* Default 64bit prefix length. */
36
+
37
+ substrings = g_strsplit(ip6_net, "/", 2);
38
+ if (!substrings || !substrings[0]) {
39
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "ipv6-net",
40
+ "a valid IPv6 prefix");
41
+ goto out;
42
+ }
43
44
- if (get_str_sep(buf, sizeof(buf), &ip6_net, '/') < 0) {
45
- /* Default 64bit prefix length. */
46
- qemu_opt_set(opts, "ipv6-prefix", ip6_net, &error_abort);
47
- qemu_opt_set_number(opts, "ipv6-prefixlen", 64, &error_abort);
48
- } else {
49
+ prefix_addr = substrings[0];
50
+
51
+ if (substrings[1]) {
52
/* User-specified prefix length. */
53
- unsigned long len;
54
int err;
55
56
- qemu_opt_set(opts, "ipv6-prefix", buf, &error_abort);
57
- err = qemu_strtoul(ip6_net, NULL, 10, &len);
58
-
59
+ err = qemu_strtoul(substrings[1], NULL, 10, &prefix_len);
60
if (err) {
61
error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
62
"ipv6-prefixlen", "a number");
63
goto out;
64
}
65
-
66
- qemu_opt_set_number(opts, "ipv6-prefixlen", len, &error_abort);
67
}
68
+
69
+ qemu_opt_set(opts, "ipv6-prefix", prefix_addr, &error_abort);
70
+ qemu_opt_set_number(opts, "ipv6-prefixlen", prefix_len,
71
+ &error_abort);
72
qemu_opt_unset(opts, "ipv6-net");
73
}
74
}
75
@@ -XXX,XX +XXX,XX @@ static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp)
76
77
out:
78
error_propagate(errp, err);
79
+ g_strfreev(substrings);
80
visit_free(v);
81
return ret;
82
}
83
--
132
--
84
2.5.0
133
2.7.4
85
86
diff view generated by jsdifflib
1
From: Stefano Garzarella <sgarzare@redhat.com>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
Since the get_str_sep() function is no longer used in
3
Running QEMU with "-nic help" used to work in QEMU 5.2 and earlier versions
4
net/net.c, we can remove it.
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.
5
8
6
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
9
Fixes: ad6f932fe8 ("net: do not exit on "netdev_add help" monitor command")
7
Reviewed-by: Markus Armbruster <armbru@redhat.com>
10
Signed-off-by: Thomas Huth <thuth@redhat.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
12
---
10
net/net.c | 20 --------------------
13
net/net.c | 14 ++++++++++++--
11
1 file changed, 20 deletions(-)
14
1 file changed, 12 insertions(+), 2 deletions(-)
12
15
13
diff --git a/net/net.c b/net/net.c
16
diff --git a/net/net.c b/net/net.c
14
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
15
--- a/net/net.c
18
--- a/net/net.c
16
+++ b/net/net.c
19
+++ b/net/net.c
17
@@ -XXX,XX +XXX,XX @@ static QTAILQ_HEAD(, NetClientState) net_clients;
20
@@ -XXX,XX +XXX,XX @@ static int net_param_nic(void *dummy, QemuOpts *opts, Error **errp)
18
/***********************************************************/
21
const char *type;
19
/* network device redirectors */
22
20
23
type = qemu_opt_get(opts, "type");
21
-static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
24
- if (type && g_str_equal(type, "none")) {
22
-{
25
- return 0; /* Nothing to do, default_net is cleared in vl.c */
23
- const char *p, *p1;
26
+ if (type) {
24
- int len;
27
+ if (g_str_equal(type, "none")) {
25
- p = *pp;
28
+ return 0; /* Nothing to do, default_net is cleared in vl.c */
26
- p1 = strchr(p, sep);
29
+ }
27
- if (!p1)
30
+ if (is_help_option(type)) {
28
- return -1;
31
+ GPtrArray *nic_models = qemu_get_nic_models(TYPE_DEVICE);
29
- len = p1 - p;
32
+ show_netdevs();
30
- p1++;
33
+ printf("\n");
31
- if (buf_size > 0) {
34
+ qemu_show_nic_models(type, (const char **)nic_models->pdata);
32
- if (len > buf_size - 1)
35
+ g_ptr_array_free(nic_models, true);
33
- len = buf_size - 1;
36
+ exit(0);
34
- memcpy(buf, p, len);
37
+ }
35
- buf[len] = '\0';
38
}
36
- }
39
37
- *pp = p1;
40
idx = nic_get_free_idx();
38
- return 0;
39
-}
40
-
41
int parse_host_port(struct sockaddr_in *saddr, const char *str,
42
Error **errp)
43
{
44
--
41
--
45
2.5.0
42
2.7.4
46
47
diff view generated by jsdifflib
1
From: Stefano Garzarella <sgarzare@redhat.com>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
If 'ipv6-prefixlen' is not a number, the current behaviour
3
Just because a NIC model is compiled into the QEMU binary does not
4
produces an assertion failure:
4
necessary mean that it can be used with each and every machine.
5
$ qemu-system-x86_64 -net user,ipv6-net=feca::0/a
5
So let's rather talk about "available" models instead of "supported"
6
qemu-system-x86_64: qemu/util/qemu-option.c:1175: qemu_opts_foreach:
6
models, just to avoid confusion.
7
Assertion `!errp || !*errp' failed.
8
Aborted (core dumped)
9
7
10
This patch fixes it, jumping to the end of the function when
8
Reviewed-by: Claudio Fontana <cfontana@suse.de>
11
'ipv6-prefixlen' is not a number, and printing the more friendly
9
Signed-off-by: Thomas Huth <thuth@redhat.com>
12
message:
13
$ qemu-system-x86_64 -net user,ipv6-net=feca::0/a
14
qemu-system-x86_64: Parameter 'ipv6-prefixlen' expects a number
15
16
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
17
Reviewed-by: Markus Armbruster <armbru@redhat.com>
18
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
19
---
11
---
20
net/net.c | 9 +++++----
12
net/net.c | 2 +-
21
1 file changed, 5 insertions(+), 4 deletions(-)
13
1 file changed, 1 insertion(+), 1 deletion(-)
22
14
23
diff --git a/net/net.c b/net/net.c
15
diff --git a/net/net.c b/net/net.c
24
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
25
--- a/net/net.c
17
--- a/net/net.c
26
+++ b/net/net.c
18
+++ b/net/net.c
27
@@ -XXX,XX +XXX,XX @@ static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp)
19
@@ -XXX,XX +XXX,XX @@ int qemu_show_nic_models(const char *arg, const char *const *models)
28
20
return 0;
29
if (err) {
30
error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
31
- "ipv6-prefix", "a number");
32
- } else {
33
- qemu_opt_set_number(opts, "ipv6-prefixlen", len,
34
- &error_abort);
35
+ "ipv6-prefixlen", "a number");
36
+ goto out;
37
}
38
+
39
+ qemu_opt_set_number(opts, "ipv6-prefixlen", len, &error_abort);
40
}
41
qemu_opt_unset(opts, "ipv6-net");
42
}
43
@@ -XXX,XX +XXX,XX @@ static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp)
44
qapi_free_NetLegacy(object);
45
}
21
}
46
22
47
+out:
23
- printf("Supported NIC models:\n");
48
error_propagate(errp, err);
24
+ printf("Available NIC models:\n");
49
visit_free(v);
25
for (i = 0 ; models[i]; i++) {
50
return ret;
26
printf("%s\n", models[i]);
27
}
51
--
28
--
52
2.5.0
29
2.7.4
53
54
diff view generated by jsdifflib
1
From: Zhang Chen <chen.zhang@intel.com>
1
From: Qiang Liu <cyruscyliu@gmail.com>
2
2
3
This patch make colo-compare can send message to remote COLO frame(Xen) when occur checkpoint.
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
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
6
Fixes: 1248f8d4cbc3 ("hw/lan9118: Add basic 16-bit mode support.")
7
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1433
8
Reported-by: Qiang Liu <cyruscyliu@gmail.com>
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>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
---
13
---
8
net/colo-compare.c | 54 ++++++++++++++++++++++++++++++++++++++++++++----------
14
hw/net/lan9118.c | 17 ++++++++---------
9
1 file changed, 44 insertions(+), 10 deletions(-)
15
1 file changed, 8 insertions(+), 9 deletions(-)
10
16
11
diff --git a/net/colo-compare.c b/net/colo-compare.c
17
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
12
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
13
--- a/net/colo-compare.c
19
--- a/hw/net/lan9118.c
14
+++ b/net/colo-compare.c
20
+++ b/hw/net/lan9118.c
15
@@ -XXX,XX +XXX,XX @@ enum {
21
@@ -XXX,XX +XXX,XX @@
16
SECONDARY_IN,
22
#include "migration/vmstate.h"
17
};
23
#include "net/net.h"
18
24
#include "net/eth.h"
19
-static void colo_compare_inconsistency_notify(void)
25
-#include "hw/hw.h"
20
-{
26
#include "hw/irq.h"
21
- notifier_list_notify(&colo_compare_notifiers,
27
#include "hw/net/lan9118.h"
22
- migrate_get_current());
28
#include "hw/ptimer.h"
23
-}
29
@@ -XXX,XX +XXX,XX @@
24
30
#ifdef DEBUG_LAN9118
25
static int compare_chr_send(CompareState *s,
31
#define DPRINTF(fmt, ...) \
26
const uint8_t *buf,
32
do { printf("lan9118: " fmt , ## __VA_ARGS__); } while (0)
27
@@ -XXX,XX +XXX,XX @@ static int compare_chr_send(CompareState *s,
33
-#define BADF(fmt, ...) \
28
uint32_t vnet_hdr_len,
34
-do { hw_error("lan9118: error: " fmt , ## __VA_ARGS__);} while (0)
29
bool notify_remote_frame);
35
#else
30
36
#define DPRINTF(fmt, ...) do {} while(0)
31
+static void notify_remote_frame(CompareState *s)
37
-#define BADF(fmt, ...) \
32
+{
38
-do { fprintf(stderr, "lan9118: error: " fmt , ## __VA_ARGS__);} while (0)
33
+ char msg[] = "DO_CHECKPOINT";
39
#endif
34
+ int ret = 0;
40
35
+
41
/* The tx and rx fifo ports are a range of aliased 32-bit registers */
36
+ ret = compare_chr_send(s, (uint8_t *)msg, strlen(msg), 0, true);
42
@@ -XXX,XX +XXX,XX @@ static uint32_t do_phy_read(lan9118_state *s, int reg)
37
+ if (ret < 0) {
43
case 30: /* Interrupt mask */
38
+ error_report("Notify Xen COLO-frame failed");
44
return s->phy_int_mask;
39
+ }
45
default:
40
+}
46
- BADF("PHY read reg %d\n", reg);
41
+
47
+ qemu_log_mask(LOG_GUEST_ERROR,
42
+static void colo_compare_inconsistency_notify(CompareState *s)
48
+ "do_phy_read: PHY read reg %d\n", reg);
43
+{
49
return 0;
44
+ if (s->notify_dev) {
45
+ notify_remote_frame(s);
46
+ } else {
47
+ notifier_list_notify(&colo_compare_notifiers,
48
+ migrate_get_current());
49
+ }
50
+}
51
+
52
static gint seq_sorter(Packet *a, Packet *b, gpointer data)
53
{
54
struct tcp_hdr *atcp, *btcp;
55
@@ -XXX,XX +XXX,XX @@ sec:
56
qemu_hexdump((char *)spkt->data, stderr,
57
"colo-compare spkt", spkt->size);
58
59
- colo_compare_inconsistency_notify();
60
+ colo_compare_inconsistency_notify(s);
61
}
50
}
62
}
51
}
63
52
@@ -XXX,XX +XXX,XX @@ static void do_phy_write(lan9118_state *s, int reg, uint32_t val)
64
@@ -XXX,XX +XXX,XX @@ void colo_compare_unregister_notifier(Notifier *notify)
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
}
65
}
60
}
66
61
67
static int colo_old_packet_check_one_conn(Connection *conn,
62
@@ -XXX,XX +XXX,XX @@ static void lan9118_16bit_mode_write(void *opaque, hwaddr offset,
68
- void *user_data)
63
return;
69
+ CompareState *s)
70
{
71
GList *result = NULL;
72
int64_t check_time = REGULAR_PACKET_CHECK_MS;
73
@@ -XXX,XX +XXX,XX @@ static int colo_old_packet_check_one_conn(Connection *conn,
74
75
if (result) {
76
/* Do checkpoint will flush old packet */
77
- colo_compare_inconsistency_notify();
78
+ colo_compare_inconsistency_notify(s);
79
return 0;
80
}
64
}
81
65
82
@@ -XXX,XX +XXX,XX @@ static void colo_old_packet_check(void *opaque)
66
- hw_error("lan9118_write: Bad size 0x%x\n", size);
83
* If we find one old packet, stop finding job and notify
67
+ qemu_log_mask(LOG_GUEST_ERROR,
84
* COLO frame do checkpoint.
68
+ "lan9118_16bit_mode_write: Bad size 0x%x\n", size);
85
*/
86
- g_queue_find_custom(&s->conn_list, NULL,
87
+ g_queue_find_custom(&s->conn_list, s,
88
(GCompareFunc)colo_old_packet_check_one_conn);
89
}
69
}
90
70
91
@@ -XXX,XX +XXX,XX @@ static void colo_compare_packet(CompareState *s, Connection *conn,
71
static uint64_t lan9118_readl(void *opaque, hwaddr offset,
92
*/
72
@@ -XXX,XX +XXX,XX @@ static uint64_t lan9118_16bit_mode_read(void *opaque, hwaddr offset,
93
trace_colo_compare_main("packet different");
73
return lan9118_readl(opaque, offset, size);
94
g_queue_push_head(&conn->primary_list, pkt);
95
- colo_compare_inconsistency_notify();
96
+
97
+ colo_compare_inconsistency_notify(s);
98
break;
99
}
100
}
74
}
101
@@ -XXX,XX +XXX,XX @@ static void compare_sec_rs_finalize(SocketReadState *sec_rs)
75
102
76
- hw_error("lan9118_read: Bad size 0x%x\n", size);
103
static void compare_notify_rs_finalize(SocketReadState *notify_rs)
77
+ qemu_log_mask(LOG_GUEST_ERROR,
104
{
78
+ "lan9118_16bit_mode_read: Bad size 0x%x\n", size);
105
+ CompareState *s = container_of(notify_rs, CompareState, notify_rs);
79
return 0;
106
+
107
/* Get Xen colo-frame's notify and handle the message */
108
+ char *data = g_memdup(notify_rs->buf, notify_rs->packet_len);
109
+ char msg[] = "COLO_COMPARE_GET_XEN_INIT";
110
+ int ret;
111
+
112
+ if (!strcmp(data, "COLO_USERSPACE_PROXY_INIT")) {
113
+ ret = compare_chr_send(s, (uint8_t *)msg, strlen(msg), 0, true);
114
+ if (ret < 0) {
115
+ error_report("Notify Xen COLO-frame INIT failed");
116
+ }
117
+ }
118
+
119
+ if (!strcmp(data, "COLO_CHECKPOINT")) {
120
+ /* colo-compare do checkpoint, flush pri packet and remove sec packet */
121
+ g_queue_foreach(&s->conn_list, colo_flush_packets, s);
122
+ }
123
}
80
}
124
81
125
/*
126
--
82
--
127
2.5.0
83
2.7.4
128
84
129
85
diff view generated by jsdifflib
1
From: Zhang Chen <chen.zhang@intel.com>
1
From: Fiona Ebner <f.ebner@proxmox.com>
2
2
3
We need to notify net filter to do checkpoint for Xen COLO, like KVM side.
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].
4
6
5
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
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>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
19
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
---
20
---
8
migration/colo.c | 2 ++
21
hw/net/vmxnet3.c | 2 +-
9
1 file changed, 2 insertions(+)
22
1 file changed, 1 insertion(+), 1 deletion(-)
10
23
11
diff --git a/migration/colo.c b/migration/colo.c
24
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
12
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
13
--- a/migration/colo.c
26
--- a/hw/net/vmxnet3.c
14
+++ b/migration/colo.c
27
+++ b/hw/net/vmxnet3.c
15
@@ -XXX,XX +XXX,XX @@ ReplicationStatus *qmp_query_xen_replication_status(Error **errp)
28
@@ -XXX,XX +XXX,XX @@ static void vmxnet3_activate_device(VMXNET3State *s)
16
void qmp_xen_colo_do_checkpoint(Error **errp)
29
vmxnet3_setup_rx_filtering(s);
17
{
30
/* Cache fields from shared memory */
18
replication_do_checkpoint_all(errp);
31
s->mtu = VMXNET3_READ_DRV_SHARED32(d, s->drv_shmem, devRead.misc.mtu);
19
+ /* Notify all filters of all NIC to do checkpoint */
32
- assert(VMXNET3_MIN_MTU <= s->mtu && s->mtu < VMXNET3_MAX_MTU);
20
+ colo_notify_filters_event(COLO_EVENT_CHECKPOINT, errp);
33
+ assert(VMXNET3_MIN_MTU <= s->mtu && s->mtu <= VMXNET3_MAX_MTU);
21
}
34
VMW_CFPRN("MTU is %u", s->mtu);
22
#endif
35
23
36
s->max_rx_frags =
24
--
37
--
25
2.5.0
38
2.7.4
26
27
diff view generated by jsdifflib
1
From: Markus Armbruster <armbru@redhat.com>
1
From: Christian Svensson <blue@cmd.nu>
2
2
3
Signed-off-by: Markus Armbruster <armbru@redhat.com>
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>
4
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
5
---
12
---
6
qemu-bridge-helper.c | 12 +++++++++++-
13
net/l2tpv3.c | 2 +-
7
1 file changed, 11 insertions(+), 1 deletion(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
8
15
9
diff --git a/qemu-bridge-helper.c b/qemu-bridge-helper.c
16
diff --git a/net/l2tpv3.c b/net/l2tpv3.c
10
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
11
--- a/qemu-bridge-helper.c
18
--- a/net/l2tpv3.c
12
+++ b/qemu-bridge-helper.c
19
+++ b/net/l2tpv3.c
13
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@
14
*
15
* This work is licensed under the terms of the GNU GPL, version 2. See
16
* the COPYING file in the top-level directory.
17
- *
18
+ */
19
+
20
+/*
21
+ * Known shortcomings:
22
+ * - There is no manual page
23
+ * - The syntax of the ACL file is not documented anywhere
24
+ * - parse_acl_file() doesn't report fopen() failure properly, fails
25
+ * to check ferror() after fgets() failure, arbitrarily truncates
26
+ * long lines, handles whitespace inconsistently, error messages
27
+ * don't point to the offending file and line, errors in included
28
+ * files are reported, but otherwise ignored, ...
29
*/
21
*/
30
22
31
#include "qemu/osdep.h"
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)
32
--
29
--
33
2.5.0
30
2.7.4
34
35
diff view generated by jsdifflib
Deleted patch
1
From: Cédric Le Goater <clg@kaod.org>
2
1
3
qdev_set_nic_properties() is already used in the Aspeed SoC level to
4
bind the ftgmac100 device to the netdev.
5
6
This is fixing support for multiple net devices.
7
8
Signed-off-by: Cédric Le Goater <clg@kaod.org>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
11
hw/net/ftgmac100.c | 2 --
12
1 file changed, 2 deletions(-)
13
14
diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/net/ftgmac100.c
17
+++ b/hw/net/ftgmac100.c
18
@@ -XXX,XX +XXX,XX @@ static void ftgmac100_realize(DeviceState *dev, Error **errp)
19
sysbus_init_irq(sbd, &s->irq);
20
qemu_macaddr_default_if_unset(&s->conf.macaddr);
21
22
- s->conf.peers.ncs[0] = nd_table[0].netdev;
23
-
24
s->nic = qemu_new_nic(&net_ftgmac100_info, &s->conf,
25
object_get_typename(OBJECT(dev)), DEVICE(dev)->id,
26
s);
27
--
28
2.5.0
29
30
diff view generated by jsdifflib
Deleted patch
1
From: Stefano Garzarella <sgarzare@redhat.com>
2
1
3
Use the glib function to split host address and port in
4
the parse_host_port() function.
5
6
Suggested-by: Markus Armbruster <armbru@redhat.com>
7
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
8
Reviewed-by: Markus Armbruster <armbru@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
11
net/net.c | 43 +++++++++++++++++++++++++++----------------
12
1 file changed, 27 insertions(+), 16 deletions(-)
13
14
diff --git a/net/net.c b/net/net.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/net/net.c
17
+++ b/net/net.c
18
@@ -XXX,XX +XXX,XX @@ static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
19
int parse_host_port(struct sockaddr_in *saddr, const char *str,
20
Error **errp)
21
{
22
- char buf[512];
23
+ gchar **substrings;
24
struct hostent *he;
25
- const char *p, *r;
26
- int port;
27
+ const char *addr, *p, *r;
28
+ int port, ret = 0;
29
30
- p = str;
31
- if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
32
+ substrings = g_strsplit(str, ":", 2);
33
+ if (!substrings || !substrings[0] || !substrings[1]) {
34
error_setg(errp, "host address '%s' doesn't contain ':' "
35
"separating host from port", str);
36
- return -1;
37
+ ret = -1;
38
+ goto out;
39
}
40
+
41
+ addr = substrings[0];
42
+ p = substrings[1];
43
+
44
saddr->sin_family = AF_INET;
45
- if (buf[0] == '\0') {
46
+ if (addr[0] == '\0') {
47
saddr->sin_addr.s_addr = 0;
48
} else {
49
- if (qemu_isdigit(buf[0])) {
50
- if (!inet_aton(buf, &saddr->sin_addr)) {
51
+ if (qemu_isdigit(addr[0])) {
52
+ if (!inet_aton(addr, &saddr->sin_addr)) {
53
error_setg(errp, "host address '%s' is not a valid "
54
- "IPv4 address", buf);
55
- return -1;
56
+ "IPv4 address", addr);
57
+ ret = -1;
58
+ goto out;
59
}
60
} else {
61
- he = gethostbyname(buf);
62
+ he = gethostbyname(addr);
63
if (he == NULL) {
64
- error_setg(errp, "can't resolve host address '%s'", buf);
65
- return - 1;
66
+ error_setg(errp, "can't resolve host address '%s'", addr);
67
+ ret = -1;
68
+ goto out;
69
}
70
saddr->sin_addr = *(struct in_addr *)he->h_addr;
71
}
72
@@ -XXX,XX +XXX,XX @@ int parse_host_port(struct sockaddr_in *saddr, const char *str,
73
port = strtol(p, (char **)&r, 0);
74
if (r == p) {
75
error_setg(errp, "port number '%s' is invalid", p);
76
- return -1;
77
+ ret = -1;
78
+ goto out;
79
}
80
saddr->sin_port = htons(port);
81
- return 0;
82
+
83
+out:
84
+ g_strfreev(substrings);
85
+ return ret;
86
}
87
88
char *qemu_mac_strdup_printf(const uint8_t *macaddr)
89
--
90
2.5.0
91
92
diff view generated by jsdifflib
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
1
From: Joelle van Dyne <j@getutm.app>
2
2
3
Previously there was a single instance of the timer used by
3
When the VM is stopped using the HMP command "stop", soon the handler will
4
monitor triggered announces, that's OK, but when combined with the
4
stop reading from the vmnet interface. This causes a flood of
5
previous change that lets you have announces for subsets of interfaces
5
`VMNET_INTERFACE_PACKETS_AVAILABLE` events to arrive and puts the host CPU
6
it's a bit restrictive if you want to do different things to different
6
at 100%. We fix this by removing the event handler from vmnet when the VM
7
interfaces.
7
is no longer in a running state and restore it when we return to a running
8
state.
8
9
9
Add an 'id' field to the announce, and maintain a list of the
10
Signed-off-by: Joelle van Dyne <j@getutm.app>
10
timers based on id.
11
12
This allows you to for example:
13
a) Start an announce going on interface eth0 for a long time
14
b) Start an announce going on interface eth1 for a long time
15
c) Kill the announce on eth0 while leaving eth1 going.
16
17
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
18
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
19
---
12
---
20
hw/net/virtio-net.c | 4 ++--
13
net/vmnet-common.m | 48 +++++++++++++++++++++++++++++++++++-------------
21
include/net/announce.h | 8 ++++++--
14
net/vmnet_int.h | 2 ++
22
net/announce.c | 52 +++++++++++++++++++++++++++++++++++++++++++-------
15
2 files changed, 37 insertions(+), 13 deletions(-)
23
net/trace-events | 3 ++-
24
qapi/net.json | 9 +++++++--
25
5 files changed, 62 insertions(+), 14 deletions(-)
26
16
27
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
17
diff --git a/net/vmnet-common.m b/net/vmnet-common.m
28
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/net/virtio-net.c
19
--- a/net/vmnet-common.m
30
+++ b/hw/net/virtio-net.c
20
+++ b/net/vmnet-common.m
31
@@ -XXX,XX +XXX,XX @@ static int virtio_net_post_load_device(void *opaque, int version_id)
32
timer_mod(n->announce_timer.tm,
33
qemu_clock_get_ms(n->announce_timer.type));
34
} else {
35
- qemu_announce_timer_del(&n->announce_timer);
36
+ qemu_announce_timer_del(&n->announce_timer, false);
37
}
38
}
39
40
@@ -XXX,XX +XXX,XX @@ static void virtio_net_device_unrealize(DeviceState *dev, Error **errp)
41
virtio_net_del_queue(n, i);
42
}
43
44
- qemu_announce_timer_del(&n->announce_timer);
45
+ qemu_announce_timer_del(&n->announce_timer, false);
46
g_free(n->vqs);
47
qemu_del_nic(n->nic);
48
virtio_net_rsc_cleanup(n);
49
diff --git a/include/net/announce.h b/include/net/announce.h
50
index XXXXXXX..XXXXXXX 100644
51
--- a/include/net/announce.h
52
+++ b/include/net/announce.h
53
@@ -XXX,XX +XXX,XX @@ struct AnnounceTimer {
54
/* Returns: update the timer to the next time point */
55
int64_t qemu_announce_timer_step(AnnounceTimer *timer);
56
57
-/* Delete the underlying timer and other data */
58
-void qemu_announce_timer_del(AnnounceTimer *timer);
59
+/*
60
+ * Delete the underlying timer and other data
61
+ * If 'free_named' true and the timer is a named timer, then remove
62
+ * it from the list of named timers and free the AnnounceTimer itself.
63
+ */
64
+void qemu_announce_timer_del(AnnounceTimer *timer, bool free_named);
65
66
/*
67
* Under BQL/main thread
68
diff --git a/net/announce.c b/net/announce.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/net/announce.c
71
+++ b/net/announce.c
72
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@
73
#include "qapi/qapi-commands-net.h"
22
#include "clients.h"
74
#include "trace.h"
23
#include "qemu/error-report.h"
75
24
#include "qapi/error.h"
76
+static GData *named_timers;
25
+#include "sysemu/runstate.h"
77
+
26
78
int64_t qemu_announce_timer_step(AnnounceTimer *timer)
27
#include <vmnet/vmnet.h>
79
{
28
#include <dispatch/dispatch.h>
80
int64_t step;
29
@@ -XXX,XX +XXX,XX @@ static void vmnet_bufs_init(VmnetState *s)
81
@@ -XXX,XX +XXX,XX @@ int64_t qemu_announce_timer_step(AnnounceTimer *timer)
82
return step;
83
}
84
85
-void qemu_announce_timer_del(AnnounceTimer *timer)
86
+/*
87
+ * If 'free_named' is true, then remove the timer from the list
88
+ * and free the timer itself.
89
+ */
90
+void qemu_announce_timer_del(AnnounceTimer *timer, bool free_named)
91
{
92
+ bool free_timer = false;
93
if (timer->tm) {
94
timer_del(timer->tm);
95
timer_free(timer->tm);
96
@@ -XXX,XX +XXX,XX @@ void qemu_announce_timer_del(AnnounceTimer *timer)
97
}
98
qapi_free_strList(timer->params.interfaces);
99
timer->params.interfaces = NULL;
100
+ if (free_named && timer->params.has_id) {
101
+ AnnounceTimer *list_timer;
102
+ /*
103
+ * Sanity check: There should only be one timer on the list with
104
+ * the id.
105
+ */
106
+ list_timer = g_datalist_get_data(&named_timers, timer->params.id);
107
+ assert(timer == list_timer);
108
+ free_timer = true;
109
+ g_datalist_remove_data(&named_timers, timer->params.id);
110
+ }
111
+ trace_qemu_announce_timer_del(free_named, free_timer, timer->params.id);
112
+ g_free(timer->params.id);
113
+ timer->params.id = NULL;
114
+
115
+ if (free_timer) {
116
+ g_free(timer);
117
+ }
118
}
119
120
/*
121
@@ -XXX,XX +XXX,XX @@ void qemu_announce_timer_reset(AnnounceTimer *timer,
122
* We're under the BQL, so the current timer can't
123
* be firing, so we should be able to delete it.
124
*/
125
- qemu_announce_timer_del(timer);
126
+ qemu_announce_timer_del(timer, false);
127
128
QAPI_CLONE_MEMBERS(AnnounceParameters, &timer->params, params);
129
timer->round = params->rounds;
130
@@ -XXX,XX +XXX,XX @@ static void qemu_announce_self_iter(NICState *nic, void *opaque)
131
skip = false;
132
}
133
134
- trace_qemu_announce_self_iter(nic->ncs->name,
135
+ trace_qemu_announce_self_iter(timer->params.has_id ? timer->params.id : "_",
136
+ nic->ncs->name,
137
qemu_ether_ntoa(&nic->conf->macaddr), skip);
138
139
if (!skip) {
140
@@ -XXX,XX +XXX,XX @@ static void qemu_announce_self_once(void *opaque)
141
if (--timer->round) {
142
qemu_announce_timer_step(timer);
143
} else {
144
- qemu_announce_timer_del(timer);
145
+ qemu_announce_timer_del(timer, true);
146
}
30
}
147
}
31
}
148
32
149
@@ -XXX,XX +XXX,XX @@ void qemu_announce_self(AnnounceTimer *timer, AnnounceParameters *params)
33
+/**
150
if (params->rounds) {
34
+ * Called on state change to un-register/re-register handlers
151
qemu_announce_self_once(timer);
35
+ */
152
} else {
36
+static void vmnet_vm_state_change_cb(void *opaque, bool running, RunState state)
153
- qemu_announce_timer_del(timer);
37
+{
154
+ qemu_announce_timer_del(timer, true);
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;
155
}
90
}
156
}
91
157
92
+ vmnet_vm_state_change_cb(s, 0, RUN_STATE_SHUTDOWN);
158
void qmp_announce_self(AnnounceParameters *params, Error **errp)
93
+ qemu_del_vm_change_state_handler(s->change);
159
{
94
if_stopped_sem = dispatch_semaphore_create(0);
160
- static AnnounceTimer announce_timer;
95
vmnet_stop_interface(
161
- qemu_announce_self(&announce_timer, params);
96
s->vmnet_if,
162
+ AnnounceTimer *named_timer;
97
diff --git a/net/vmnet_int.h b/net/vmnet_int.h
163
+ if (!params->has_id) {
98
index XXXXXXX..XXXXXXX 100644
164
+ params->id = g_strdup("");
99
--- a/net/vmnet_int.h
165
+ params->has_id = true;
100
+++ b/net/vmnet_int.h
166
+ }
101
@@ -XXX,XX +XXX,XX @@ typedef struct VmnetState {
102
int packets_send_end_pos;
103
104
struct iovec iov_buf[VMNET_PACKETS_LIMIT];
167
+
105
+
168
+ named_timer = g_datalist_get_data(&named_timers, params->id);
106
+ VMChangeStateEntry *change;
169
+
107
} VmnetState;
170
+ if (!named_timer) {
108
171
+ named_timer = g_new0(AnnounceTimer, 1);
109
const char *vmnet_status_map_str(vmnet_return_t status);
172
+ g_datalist_set_data(&named_timers, params->id, named_timer);
173
+ }
174
+
175
+ qemu_announce_self(named_timer, params);
176
}
177
diff --git a/net/trace-events b/net/trace-events
178
index XXXXXXX..XXXXXXX 100644
179
--- a/net/trace-events
180
+++ b/net/trace-events
181
@@ -XXX,XX +XXX,XX @@
182
# See docs/devel/tracing.txt for syntax documentation.
183
184
# announce.c
185
-qemu_announce_self_iter(const char *name, const char *mac, int skip) "%s:%s skip: %d"
186
+qemu_announce_self_iter(const char *id, const char *name, const char *mac, int skip) "%s:%s:%s skip: %d"
187
+qemu_announce_timer_del(bool free_named, bool free_timer, char *id) "free named: %d free timer: %d id: %s"
188
189
# vhost-user.c
190
vhost_user_event(const char *chr, int event) "chr: %s got event: %d"
191
diff --git a/qapi/net.json b/qapi/net.json
192
index XXXXXXX..XXXXXXX 100644
193
--- a/qapi/net.json
194
+++ b/qapi/net.json
195
@@ -XXX,XX +XXX,XX @@
196
# @interfaces: An optional list of interface names, which restricts the
197
# announcement to the listed interfaces. (Since 4.1)
198
#
199
+# @id: A name to be used to identify an instance of announce-timers
200
+# and to allow it to modified later. Not for use as
201
+# part of the migration parameters. (Since 4.1)
202
+#
203
# Since: 4.0
204
##
205
206
@@ -XXX,XX +XXX,XX @@
207
'max': 'int',
208
'rounds': 'int',
209
'step': 'int',
210
- '*interfaces': ['str'] } }
211
+ '*interfaces': ['str'],
212
+ '*id' : 'str' } }
213
214
##
215
# @announce-self:
216
@@ -XXX,XX +XXX,XX @@
217
# -> { "execute": "announce-self",
218
# "arguments": {
219
# "initial": 50, "max": 550, "rounds": 10, "step": 50,
220
-# "interfaces": ["vn2", "vn3"] } }
221
+# "interfaces": ["vn2", "vn3"], "id": "bob" } }
222
# <- { "return": {} }
223
#
224
# Since: 4.0
225
--
110
--
226
2.5.0
111
2.7.4
227
228
diff view generated by jsdifflib
1
From: Zhang Chen <chen.zhang@intel.com>
1
From: Qiang Liu <cyruscyliu@gmail.com>
2
2
3
We add the "notify_dev=chardevID" parameter. After that colo-compare can connect with
3
Check fifos before poping data from and pushing data into it.
4
remote(currently just for Xen, KVM-COLO didn't need it.) colo-frame through chardev socket,
5
it can notify remote(Xen) colo-frame to handle checkpoint event.
6
4
7
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
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>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
11
---
10
net/colo-compare.c | 21 +++++++++++++++++++++
12
hw/net/can/xlnx-zynqmp-can.c | 9 ++++++++-
11
qemu-options.hx | 33 ++++++++++++++++++++++++++++++++-
13
1 file changed, 8 insertions(+), 1 deletion(-)
12
2 files changed, 53 insertions(+), 1 deletion(-)
13
14
14
diff --git a/net/colo-compare.c b/net/colo-compare.c
15
diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/net/colo-compare.c
17
--- a/hw/net/can/xlnx-zynqmp-can.c
17
+++ b/net/colo-compare.c
18
+++ b/hw/net/can/xlnx-zynqmp-can.c
18
@@ -XXX,XX +XXX,XX @@ typedef struct CompareState {
19
@@ -XXX,XX +XXX,XX @@ static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo)
19
char *pri_indev;
20
}
20
char *sec_indev;
21
21
char *outdev;
22
while (!fifo32_is_empty(fifo)) {
22
+ char *notify_dev;
23
+ if (fifo32_num_used(fifo) < (4 * CAN_FRAME_SIZE)) {
23
CharBackend chr_pri_in;
24
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
24
CharBackend chr_sec_in;
25
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: data left in the fifo is not"
25
CharBackend chr_out;
26
+ " enough for transfer.\n", path);
26
@@ -XXX,XX +XXX,XX @@ static void compare_set_vnet_hdr(Object *obj,
27
+ break;
27
s->vnet_hdr = value;
28
+ }
28
}
29
for (i = 0; i < CAN_FRAME_SIZE; i++) {
29
30
data[i] = fifo32_pop(fifo);
30
+static char *compare_get_notify_dev(Object *obj, Error **errp)
31
}
31
+{
32
@@ -XXX,XX +XXX,XX @@ static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo)
32
+ CompareState *s = COLO_COMPARE(obj);
33
* acknowledged. The XlnxZynqMPCAN core receives any message
33
+
34
* that it transmits.
34
+ return g_strdup(s->notify_dev);
35
*/
35
+}
36
- if (fifo32_is_full(&s->rx_fifo)) {
36
+
37
+ if (fifo32_is_full(&s->rx_fifo) ||
37
+static void compare_set_notify_dev(Object *obj, const char *value, Error **errp)
38
+ (fifo32_num_free(&s->rx_fifo) < (4 * CAN_FRAME_SIZE))) {
38
+{
39
ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 1);
39
+ CompareState *s = COLO_COMPARE(obj);
40
} else {
40
+
41
for (i = 0; i < CAN_FRAME_SIZE; i++) {
41
+ g_free(s->notify_dev);
42
+ s->notify_dev = g_strdup(value);
43
+}
44
+
45
static void compare_pri_rs_finalize(SocketReadState *pri_rs)
46
{
47
CompareState *s = container_of(pri_rs, CompareState, pri_rs);
48
@@ -XXX,XX +XXX,XX @@ static void colo_compare_init(Object *obj)
49
(Object **)&s->iothread,
50
object_property_allow_set_link,
51
OBJ_PROP_LINK_STRONG, NULL);
52
+ /* This parameter just for Xen COLO */
53
+ object_property_add_str(obj, "notify_dev",
54
+ compare_get_notify_dev, compare_set_notify_dev,
55
+ NULL);
56
57
s->vnet_hdr = false;
58
object_property_add_bool(obj, "vnet_hdr_support", compare_get_vnet_hdr,
59
@@ -XXX,XX +XXX,XX @@ static void colo_compare_finalize(Object *obj)
60
g_free(s->pri_indev);
61
g_free(s->sec_indev);
62
g_free(s->outdev);
63
+ g_free(s->notify_dev);
64
}
65
66
static const TypeInfo colo_compare_info = {
67
diff --git a/qemu-options.hx b/qemu-options.hx
68
index XXXXXXX..XXXXXXX 100644
69
--- a/qemu-options.hx
70
+++ b/qemu-options.hx
71
@@ -XXX,XX +XXX,XX @@ Dump the network traffic on netdev @var{dev} to the file specified by
72
The file format is libpcap, so it can be analyzed with tools such as tcpdump
73
or Wireshark.
74
75
-@item -object colo-compare,id=@var{id},primary_in=@var{chardevid},secondary_in=@var{chardevid},outdev=@var{chardevid},iothread=@var{id}[,vnet_hdr_support]
76
+@item -object colo-compare,id=@var{id},primary_in=@var{chardevid},secondary_in=@var{chardevid},outdev=@var{chardevid},iothread=@var{id}[,vnet_hdr_support][,notify_dev=@var{id}]
77
78
Colo-compare gets packet from primary_in@var{chardevid} and secondary_in@var{chardevid}, than compare primary packet with
79
secondary packet. If the packets are same, we will output primary
80
@@ -XXX,XX +XXX,XX @@ do checkpoint and send primary packet to outdev@var{chardevid}.
81
In order to improve efficiency, we need to put the task of comparison
82
in another thread. If it has the vnet_hdr_support flag, colo compare
83
will send/recv packet with vnet_hdr_len.
84
+If you want to use Xen COLO, will need the notify_dev to notify Xen
85
+colo-frame to do checkpoint.
86
87
we must use it with the help of filter-mirror and filter-redirector.
88
89
@example
90
91
+KVM COLO
92
+
93
primary:
94
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown
95
-device e1000,id=e0,netdev=hn0,mac=52:a4:00:12:78:66
96
@@ -XXX,XX +XXX,XX @@ secondary:
97
-object filter-redirector,id=f1,netdev=hn0,queue=tx,indev=red0
98
-object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1
99
100
+
101
+Xen COLO
102
+
103
+primary:
104
+-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown
105
+-device e1000,id=e0,netdev=hn0,mac=52:a4:00:12:78:66
106
+-chardev socket,id=mirror0,host=3.3.3.3,port=9003,server,nowait
107
+-chardev socket,id=compare1,host=3.3.3.3,port=9004,server,nowait
108
+-chardev socket,id=compare0,host=3.3.3.3,port=9001,server,nowait
109
+-chardev socket,id=compare0-0,host=3.3.3.3,port=9001
110
+-chardev socket,id=compare_out,host=3.3.3.3,port=9005,server,nowait
111
+-chardev socket,id=compare_out0,host=3.3.3.3,port=9005
112
+-chardev socket,id=notify_way,host=3.3.3.3,port=9009,server,nowait
113
+-object filter-mirror,id=m0,netdev=hn0,queue=tx,outdev=mirror0
114
+-object filter-redirector,netdev=hn0,id=redire0,queue=rx,indev=compare_out
115
+-object filter-redirector,netdev=hn0,id=redire1,queue=rx,outdev=compare0
116
+-object iothread,id=iothread1
117
+-object colo-compare,id=comp0,primary_in=compare0-0,secondary_in=compare1,outdev=compare_out0,notify_dev=nofity_way,iothread=iothread1
118
+
119
+secondary:
120
+-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,down script=/etc/qemu-ifdown
121
+-device e1000,netdev=hn0,mac=52:a4:00:12:78:66
122
+-chardev socket,id=red0,host=3.3.3.3,port=9003
123
+-chardev socket,id=red1,host=3.3.3.3,port=9004
124
+-object filter-redirector,id=f1,netdev=hn0,queue=tx,indev=red0
125
+-object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1
126
+
127
@end example
128
129
If you want to know the detail of above command line, you can read
130
--
42
--
131
2.5.0
43
2.7.4
132
133
diff view generated by jsdifflib
1
From: Zhang Chen <chen.zhang@intel.com>
1
From: Laurent Vivier <lvivier@redhat.com>
2
2
3
Add chardev handler to send notification to remote(current from Xen) colo-frame.
3
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
4
4
Acked-by: Michael S. Tsirkin <mst@redhat.com>
5
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
5
Acked-by: Thomas Huth <thuth@redhat.com>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
---
7
---
8
net/colo-compare.c | 39 +++++++++++++++++++++++++++++++++++++++
8
tests/qtest/meson.build | 2 +
9
1 file changed, 39 insertions(+)
9
tests/qtest/netdev-socket.c | 448 ++++++++++++++++++++++++++++++++++++++++++++
10
2 files changed, 450 insertions(+)
11
create mode 100644 tests/qtest/netdev-socket.c
10
12
11
diff --git a/net/colo-compare.c b/net/colo-compare.c
13
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
12
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
13
--- a/net/colo-compare.c
15
--- a/tests/qtest/meson.build
14
+++ b/net/colo-compare.c
16
+++ b/tests/qtest/meson.build
15
@@ -XXX,XX +XXX,XX @@ typedef struct CompareState {
17
@@ -XXX,XX +XXX,XX @@ qtests_generic = [
16
CharBackend chr_pri_in;
18
'test-hmp',
17
CharBackend chr_sec_in;
19
'qos-test',
18
CharBackend chr_out;
20
'readconfig-test',
19
+ CharBackend chr_notify_dev;
21
+ 'netdev-socket',
20
SocketReadState pri_rs;
22
]
21
SocketReadState sec_rs;
23
if config_host.has_key('CONFIG_MODULES')
22
+ SocketReadState notify_rs;
24
qtests_generic += [ 'modules-test' ]
23
bool vnet_hdr;
25
@@ -XXX,XX +XXX,XX @@ qtests = {
24
26
'tpm-tis-device-swtpm-test': [io, tpmemu_files, 'tpm-tis-util.c'],
25
/*
27
'tpm-tis-device-test': [io, tpmemu_files, 'tpm-tis-util.c'],
26
@@ -XXX,XX +XXX,XX @@ static void compare_sec_chr_in(void *opaque, const uint8_t *buf, int size)
28
'vmgenid-test': files('boot-sector.c', 'acpi-utils.c'),
27
}
29
+ 'netdev-socket': files('netdev-socket.c', '../unit/socket-helpers.c'),
28
}
30
}
29
31
30
+static void compare_notify_chr(void *opaque, const uint8_t *buf, int size)
32
gvnc = dependency('gvnc-1.0', required: false)
31
+{
33
diff --git a/tests/qtest/netdev-socket.c b/tests/qtest/netdev-socket.c
32
+ CompareState *s = COLO_COMPARE(opaque);
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];
33
+ int ret;
282
+ int ret;
34
+
283
+
35
+ ret = net_fill_rstate(&s->notify_rs, buf, size);
284
+ ret = socketpair(AF_LOCAL, SOCK_STREAM, 0, sock);
36
+ if (ret == -1) {
285
+ g_assert_true(ret == 0);
37
+ qemu_chr_fe_set_handlers(&s->chr_notify_dev, NULL, NULL, NULL, NULL,
286
+
38
+ NULL, NULL, true);
287
+ qts0 = qtest_initf("-nodefaults -M none "
39
+ error_report("colo-compare notify_dev error");
288
+ "-netdev stream,id=st0,addr.type=fd,addr.str=%d",
40
+ }
289
+ sock[0]);
41
+}
290
+
42
+
291
+ EXPECT_STATE(qts0, "st0: index=0,type=stream,unix:\r\n", 0);
43
/*
292
+
44
* Check old packet regularly so it can watch for any packets
293
+ qts1 = qtest_initf("-nodefaults -M none "
45
* that the secondary hasn't produced equivalents of.
294
+ "-netdev stream,id=st0,addr.type=fd,addr.str=%d",
46
@@ -XXX,XX +XXX,XX @@ static void colo_compare_iothread(CompareState *s)
295
+ sock[1]);
47
qemu_chr_fe_set_handlers(&s->chr_sec_in, compare_chr_can_read,
296
+
48
compare_sec_chr_in, NULL, NULL,
297
+ EXPECT_STATE(qts1, "st0: index=0,type=stream,unix:\r\n", 0);
49
s, s->worker_context, true);
298
+ EXPECT_STATE(qts0, "st0: index=0,type=stream,unix:\r\n", 0);
50
+ if (s->notify_dev) {
299
+
51
+ qemu_chr_fe_set_handlers(&s->chr_notify_dev, compare_chr_can_read,
300
+ qtest_quit(qts1);
52
+ compare_notify_chr, NULL, NULL,
301
+ qtest_quit(qts0);
53
+ s, s->worker_context, true);
302
+
54
+ }
303
+ closesocket(sock[0]);
55
304
+ closesocket(sock[1]);
56
colo_compare_timer_init(s);
305
+}
57
s->event_bh = qemu_bh_new(colo_compare_handle_event, s);
306
+#endif
58
@@ -XXX,XX +XXX,XX @@ static void compare_sec_rs_finalize(SocketReadState *sec_rs)
307
+
59
}
308
+static void test_dgram_inet(void)
60
}
309
+{
61
310
+ QTestState *qts0, *qts1;
62
+static void compare_notify_rs_finalize(SocketReadState *notify_rs)
311
+ char *expect;
63
+{
312
+ int port[2];
64
+ /* Get Xen colo-frame's notify and handle the message */
313
+ int nb;
65
+}
314
+
66
315
+ nb = inet_get_free_port_multiple(2, port, false);
67
/*
316
+ g_assert_cmpint(nb, ==, 2);
68
* Return 0 is success.
317
+
69
@@ -XXX,XX +XXX,XX @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
318
+ qts0 = qtest_initf("-nodefaults -M none "
70
net_socket_rs_init(&s->pri_rs, compare_pri_rs_finalize, s->vnet_hdr);
319
+ "-netdev dgram,id=st0,"
71
net_socket_rs_init(&s->sec_rs, compare_sec_rs_finalize, s->vnet_hdr);
320
+ "local.type=inet,local.host=127.0.0.1,local.port=%d,"
72
321
+ "remote.type=inet,remote.host=127.0.0.1,remote.port=%d",
73
+ /* Try to enable remote notify chardev, currently just for Xen COLO */
322
+ port[0], port[1]);
74
+ if (s->notify_dev) {
323
+
75
+ if (find_and_check_chardev(&chr, s->notify_dev, errp) ||
324
+ expect = g_strdup_printf("st0: index=0,type=dgram,"
76
+ !qemu_chr_fe_init(&s->chr_notify_dev, chr, errp)) {
325
+ "udp=127.0.0.1:%d/127.0.0.1:%d\r\n",
77
+ return;
326
+ port[0], port[1]);
78
+ }
327
+ EXPECT_STATE(qts0, expect, 0);
79
+
328
+ g_free(expect);
80
+ net_socket_rs_init(&s->notify_rs, compare_notify_rs_finalize,
329
+
81
+ s->vnet_hdr);
330
+ qts1 = qtest_initf("-nodefaults -M none "
82
+ }
331
+ "-netdev dgram,id=st0,"
83
+
332
+ "local.type=inet,local.host=127.0.0.1,local.port=%d,"
84
QTAILQ_INSERT_TAIL(&net_compares, s, next);
333
+ "remote.type=inet,remote.host=127.0.0.1,remote.port=%d",
85
334
+ port[1], port[0]);
86
g_queue_init(&s->conn_list);
335
+
87
@@ -XXX,XX +XXX,XX @@ static void colo_compare_finalize(Object *obj)
336
+ expect = g_strdup_printf("st0: index=0,type=dgram,"
88
qemu_chr_fe_deinit(&s->chr_pri_in, false);
337
+ "udp=127.0.0.1:%d/127.0.0.1:%d\r\n",
89
qemu_chr_fe_deinit(&s->chr_sec_in, false);
338
+ port[1], port[0]);
90
qemu_chr_fe_deinit(&s->chr_out, false);
339
+ EXPECT_STATE(qts1, expect, 0);
91
+ if (s->notify_dev) {
340
+ g_free(expect);
92
+ qemu_chr_fe_deinit(&s->chr_notify_dev, false);
341
+
93
+ }
342
+ qtest_quit(qts1);
94
+
343
+ qtest_quit(qts0);
95
if (s->iothread) {
344
+}
96
colo_compare_timer_del(s);
345
+
97
}
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
+}
98
--
487
--
99
2.5.0
488
2.7.4
100
101
diff view generated by jsdifflib
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
1
From: Laurent Vivier <lvivier@redhat.com>
2
2
3
Allow the caller to restrict the set of interfaces that announces are
3
In stream mode, if the server shuts down there is currently
4
sent on. The default is still to send on all interfaces.
4
no way to reconnect the client to a new server without removing
5
5
the NIC device and the netdev backend (or to reboot).
6
e.g.
6
7
7
This patch introduces a reconnect option that specifies a delay
8
{ "execute": "announce-self", "arguments": { "initial": 50, "max": 550, "rounds": 5, "step": 50, "interfaces": ["vn2", "vn1"] } }
8
to try to reconnect with the same parameters.
9
9
10
This doesn't affect the behaviour of migraiton announcments.
10
Add a new test in qtest to test the reconnect option and the
11
11
connect/disconnect events.
12
Note: There's still only one timer for the qmp command, so that
12
13
performing an 'announce-self' on one list of interfaces followed
13
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
14
by another 'announce-self' on another list will stop the announces
15
on the existing set.
16
17
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
18
Signed-off-by: Jason Wang <jasowang@redhat.com>
14
Signed-off-by: Jason Wang <jasowang@redhat.com>
19
---
15
---
20
include/net/announce.h | 2 +-
16
net/stream.c | 53 ++++++++++++++++++++++-
21
net/announce.c | 39 ++++++++++++++++++++++++++++++++-------
17
qapi/net.json | 7 ++-
22
net/trace-events | 2 +-
18
qemu-options.hx | 6 +--
23
qapi/net.json | 11 ++++++++---
19
tests/qtest/netdev-socket.c | 101 ++++++++++++++++++++++++++++++++++++++++++++
24
4 files changed, 42 insertions(+), 12 deletions(-)
20
4 files changed, 162 insertions(+), 5 deletions(-)
25
21
26
diff --git a/include/net/announce.h b/include/net/announce.h
22
diff --git a/net/stream.c b/net/stream.c
27
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
28
--- a/include/net/announce.h
24
--- a/net/stream.c
29
+++ b/include/net/announce.h
25
+++ b/net/stream.c
30
@@ -XXX,XX +XXX,XX @@ struct AnnounceTimer {
26
@@ -XXX,XX +XXX,XX @@
31
/* Returns: update the timer to the next time point */
27
#include "io/channel-socket.h"
32
int64_t qemu_announce_timer_step(AnnounceTimer *timer);
28
#include "io/net-listener.h"
33
29
#include "qapi/qapi-events-net.h"
34
-/* Delete the underlying timer */
30
+#include "qapi/qapi-visit-sockets.h"
35
+/* Delete the underlying timer and other data */
31
+#include "qapi/clone-visitor.h"
36
void qemu_announce_timer_del(AnnounceTimer *timer);
32
37
33
typedef struct NetStreamState {
38
/*
34
NetClientState nc;
39
diff --git a/net/announce.c b/net/announce.c
35
@@ -XXX,XX +XXX,XX @@ typedef struct NetStreamState {
40
index XXXXXXX..XXXXXXX 100644
36
guint ioc_write_tag;
41
--- a/net/announce.c
37
SocketReadState rs;
42
+++ b/net/announce.c
38
unsigned int send_index; /* number of bytes sent*/
43
@@ -XXX,XX +XXX,XX @@ void qemu_announce_timer_del(AnnounceTimer *timer)
39
+ uint32_t reconnect;
44
timer_free(timer->tm);
40
+ guint timer_tag;
45
timer->tm = NULL;
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;
46
}
58
}
47
+ qapi_free_strList(timer->params.interfaces);
59
@@ -XXX,XX +XXX,XX @@ static gboolean net_stream_send(QIOChannel *ioc,
48
+ timer->params.interfaces = NULL;
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
+ }
49
}
102
}
50
103
51
/*
104
static int net_stream_client_init(NetClientState *peer,
52
@@ -XXX,XX +XXX,XX @@ static int announce_self_create(uint8_t *buf,
105
const char *model,
53
106
const char *name,
54
static void qemu_announce_self_iter(NICState *nic, void *opaque)
107
SocketAddress *addr,
108
+ uint32_t reconnect,
109
Error **errp)
55
{
110
{
56
+ AnnounceTimer *timer = opaque;
111
NetStreamState *s;
57
uint8_t buf[60];
112
@@ -XXX,XX +XXX,XX @@ static int net_stream_client_init(NetClientState *peer,
58
int len;
113
s->ioc = QIO_CHANNEL(sioc);
59
+ bool skip;
114
s->nc.link_down = true;
60
+
115
61
+ if (timer->params.has_interfaces) {
116
+ s->reconnect = reconnect;
62
+ strList *entry = timer->params.interfaces;
117
+ if (reconnect) {
63
+ /* Skip unless we find our name in the requested list */
118
+ s->addr = QAPI_CLONE(SocketAddress, addr);
64
+ skip = true;
119
+ }
65
+
120
qio_channel_socket_connect_async(sioc, addr,
66
+ while (entry) {
121
net_stream_client_connected, s,
67
+ if (!strcmp(entry->value, nic->ncs->name)) {
122
NULL, NULL);
68
+ /* Found us */
123
@@ -XXX,XX +XXX,XX @@ int net_init_stream(const Netdev *netdev, const char *name,
69
+ skip = false;
124
sock = &netdev->u.stream;
70
+ break;
125
71
+ }
126
if (!sock->has_server || !sock->server) {
72
+ entry = entry->next;
127
- return net_stream_client_init(peer, "stream", name, sock->addr, errp);
73
+ }
128
+ return net_stream_client_init(peer, "stream", name, sock->addr,
74
+ } else {
129
+ sock->has_reconnect ? sock->reconnect : 0,
75
+ skip = false;
130
+ errp);
76
+ }
131
+ }
77
+
132
+ if (sock->has_reconnect) {
78
+ trace_qemu_announce_self_iter(nic->ncs->name,
133
+ error_setg(errp, "'reconnect' option is incompatible with "
79
+ qemu_ether_ntoa(&nic->conf->macaddr), skip);
134
+ "socket in server mode");
80
135
+ return -1;
81
- trace_qemu_announce_self_iter(qemu_ether_ntoa(&nic->conf->macaddr));
82
- len = announce_self_create(buf, nic->conf->macaddr.a);
83
+ if (!skip) {
84
+ len = announce_self_create(buf, nic->conf->macaddr.a);
85
86
- qemu_send_packet_raw(qemu_get_queue(nic), buf, len);
87
+ qemu_send_packet_raw(qemu_get_queue(nic), buf, len);
88
89
- /* if the NIC provides it's own announcement support, use it as well */
90
- if (nic->ncs->info->announce) {
91
- nic->ncs->info->announce(nic->ncs);
92
+ /* if the NIC provides it's own announcement support, use it as well */
93
+ if (nic->ncs->info->announce) {
94
+ nic->ncs->info->announce(nic->ncs);
95
+ }
96
}
136
}
137
return net_stream_server_init(peer, "stream", name, sock->addr, errp);
97
}
138
}
98
static void qemu_announce_self_once(void *opaque)
99
{
100
AnnounceTimer *timer = (AnnounceTimer *)opaque;
101
102
- qemu_foreach_nic(qemu_announce_self_iter, NULL);
103
+ qemu_foreach_nic(qemu_announce_self_iter, timer);
104
105
if (--timer->round) {
106
qemu_announce_timer_step(timer);
107
diff --git a/net/trace-events b/net/trace-events
108
index XXXXXXX..XXXXXXX 100644
109
--- a/net/trace-events
110
+++ b/net/trace-events
111
@@ -XXX,XX +XXX,XX @@
112
# See docs/devel/tracing.txt for syntax documentation.
113
114
# announce.c
115
-qemu_announce_self_iter(const char *mac) "%s"
116
+qemu_announce_self_iter(const char *name, const char *mac, int skip) "%s:%s skip: %d"
117
118
# vhost-user.c
119
vhost_user_event(const char *chr, int event) "chr: %s got event: %d"
120
diff --git a/qapi/net.json b/qapi/net.json
139
diff --git a/qapi/net.json b/qapi/net.json
121
index XXXXXXX..XXXXXXX 100644
140
index XXXXXXX..XXXXXXX 100644
122
--- a/qapi/net.json
141
--- a/qapi/net.json
123
+++ b/qapi/net.json
142
+++ b/qapi/net.json
124
@@ -XXX,XX +XXX,XX @@
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)
125
#
151
#
126
# @step: Delay increase (in ms) after each self-announcement attempt
152
# Only SocketAddress types 'unix', 'inet' and 'fd' are supported.
127
#
153
#
128
+# @interfaces: An optional list of interface names, which restricts the
154
@@ -XXX,XX +XXX,XX @@
129
+# announcement to the listed interfaces. (Since 4.1)
155
{ 'struct': 'NetdevStreamOptions',
130
+#
156
'data': {
131
# Since: 4.0
157
'addr': 'SocketAddress',
158
- '*server': 'bool' } }
159
+ '*server': 'bool',
160
+ '*reconnect': 'uint32' } }
161
132
##
162
##
133
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
134
@@ -XXX,XX +XXX,XX @@
185
@@ -XXX,XX +XXX,XX @@
135
'data': { 'initial': 'int',
186
#include <glib/gstdio.h>
136
'max': 'int',
187
#include "../unit/socket-helpers.h"
137
'rounds': 'int',
188
#include "libqtest.h"
138
- 'step': 'int' } }
189
+#include "qapi/qmp/qstring.h"
139
+ 'step': 'int',
190
+#include "qemu/sockets.h"
140
+ '*interfaces': ['str'] } }
191
+#include "qapi/qobject-input-visitor.h"
141
192
+#include "qapi/qapi-visit-sockets.h"
142
##
193
143
# @announce-self:
194
#define CONNECTION_TIMEOUT 5
144
@@ -XXX,XX +XXX,XX @@
195
145
#
196
@@ -XXX,XX +XXX,XX @@ static void test_stream_inet_ipv4(void)
146
# Example:
197
qtest_quit(qts0);
147
#
198
}
148
-# -> { "execute": "announce-self"
199
149
+# -> { "execute": "announce-self",
200
+static void wait_stream_connected(QTestState *qts, const char *id,
150
# "arguments": {
201
+ SocketAddress **addr)
151
-# "initial": 50, "max": 550, "rounds": 10, "step": 50 } }
202
+{
152
+# "initial": 50, "max": 550, "rounds": 10, "step": 50,
203
+ QDict *resp, *data;
153
+# "interfaces": ["vn2", "vn3"] } }
204
+ QString *qstr;
154
# <- { "return": {} }
205
+ QObject *obj;
155
#
206
+ Visitor *v = NULL;
156
# Since: 4.0
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);
157
--
307
--
158
2.5.0
308
2.7.4
159
160
diff view generated by jsdifflib
Deleted patch
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
2
1
3
Add the optional interface list to the HMP command.
4
5
i.e.
6
7
All interfaces
8
announce_self
9
10
Just the named interfaces:
11
announce_self vn1,vn2
12
13
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
14
Signed-off-by: Jason Wang <jasowang@redhat.com>
15
---
16
hmp-commands.hx | 6 ++++--
17
monitor/hmp-cmds.c | 38 +++++++++++++++++++++++++++++++++++++-
18
2 files changed, 41 insertions(+), 3 deletions(-)
19
20
diff --git a/hmp-commands.hx b/hmp-commands.hx
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hmp-commands.hx
23
+++ b/hmp-commands.hx
24
@@ -XXX,XX +XXX,XX @@ ETEXI
25
26
{
27
.name = "announce_self",
28
- .args_type = "",
29
- .params = "",
30
+ .args_type = "interfaces:s?",
31
+ .params = "[interfaces]",
32
.help = "Trigger GARP/RARP announcements",
33
.cmd = hmp_announce_self,
34
},
35
@@ -XXX,XX +XXX,XX @@ STEXI
36
Trigger a round of GARP/RARP broadcasts; this is useful for explicitly updating the
37
network infrastructure after a reconfiguration or some forms of migration.
38
The timings of the round are set by the migration announce parameters.
39
+An optional comma separated @var{interfaces} list restricts the announce to the
40
+named set of interfaces.
41
ETEXI
42
43
{
44
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/monitor/hmp-cmds.c
47
+++ b/monitor/hmp-cmds.c
48
@@ -XXX,XX +XXX,XX @@
49
#include "monitor/monitor-internal.h"
50
#include "monitor/qdev.h"
51
#include "qapi/error.h"
52
+#include "qapi/clone-visitor.h"
53
#include "qapi/opts-visitor.h"
54
#include "qapi/qapi-builtin-visit.h"
55
#include "qapi/qapi-commands-block.h"
56
@@ -XXX,XX +XXX,XX @@
57
#include "qapi/qapi-commands-run-state.h"
58
#include "qapi/qapi-commands-tpm.h"
59
#include "qapi/qapi-commands-ui.h"
60
+#include "qapi/qapi-visit-net.h"
61
#include "qapi/qmp/qdict.h"
62
#include "qapi/qmp/qerror.h"
63
#include "qapi/string-input-visitor.h"
64
@@ -XXX,XX +XXX,XX @@ static void hmp_handle_error(Monitor *mon, Error **errp)
65
}
66
}
67
68
+/*
69
+ * Produce a strList from a comma separated list.
70
+ * A NULL or empty input string return NULL.
71
+ */
72
+static strList *strList_from_comma_list(const char *in)
73
+{
74
+ strList *res = NULL;
75
+ strList **hook = &res;
76
+
77
+ while (in && in[0]) {
78
+ char *comma = strchr(in, ',');
79
+ *hook = g_new0(strList, 1);
80
+
81
+ if (comma) {
82
+ (*hook)->value = g_strndup(in, comma - in);
83
+ in = comma + 1; /* skip the , */
84
+ } else {
85
+ (*hook)->value = g_strdup(in);
86
+ in = NULL;
87
+ }
88
+ hook = &(*hook)->next;
89
+ }
90
+
91
+ return res;
92
+}
93
+
94
void hmp_info_name(Monitor *mon, const QDict *qdict)
95
{
96
NameInfo *info;
97
@@ -XXX,XX +XXX,XX @@ void hmp_info_snapshots(Monitor *mon, const QDict *qdict)
98
99
void hmp_announce_self(Monitor *mon, const QDict *qdict)
100
{
101
- qmp_announce_self(migrate_announce_params(), NULL);
102
+ const char *interfaces_str = qdict_get_try_str(qdict, "interfaces");
103
+ AnnounceParameters *params = QAPI_CLONE(AnnounceParameters,
104
+ migrate_announce_params());
105
+
106
+ qapi_free_strList(params->interfaces);
107
+ params->interfaces = strList_from_comma_list(interfaces_str);
108
+ params->has_interfaces = params->interfaces != NULL;
109
+ qmp_announce_self(params, NULL);
110
+ qapi_free_AnnounceParameters(params);
111
}
112
113
void hmp_migrate_cancel(Monitor *mon, const QDict *qdict)
114
--
115
2.5.0
116
117
diff view generated by jsdifflib
Deleted patch
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
2
1
3
Add the optional ID to the HMP command.
4
5
e.g.
6
# start an announce for a long time on eth1
7
migrate_set_parameter announce-rounds 1000
8
announce_self "eth1" e1
9
10
# start an announce on eth2
11
announce_self "eth2" e2
12
13
# Change e1 to be announcing on eth1 and eth3
14
announce_self "eth1,eth3" e1
15
16
# Cancel e1
17
migrate_set_parameter announce-rounds 0
18
announce_self "" e1
19
20
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
21
Signed-off-by: Jason Wang <jasowang@redhat.com>
22
---
23
hmp-commands.hx | 7 ++++---
24
monitor/hmp-cmds.c | 3 +++
25
2 files changed, 7 insertions(+), 3 deletions(-)
26
27
diff --git a/hmp-commands.hx b/hmp-commands.hx
28
index XXXXXXX..XXXXXXX 100644
29
--- a/hmp-commands.hx
30
+++ b/hmp-commands.hx
31
@@ -XXX,XX +XXX,XX @@ ETEXI
32
33
{
34
.name = "announce_self",
35
- .args_type = "interfaces:s?",
36
- .params = "[interfaces]",
37
+ .args_type = "interfaces:s?,id:s?",
38
+ .params = "[interfaces] [id]",
39
.help = "Trigger GARP/RARP announcements",
40
.cmd = hmp_announce_self,
41
},
42
@@ -XXX,XX +XXX,XX @@ Trigger a round of GARP/RARP broadcasts; this is useful for explicitly updating
43
network infrastructure after a reconfiguration or some forms of migration.
44
The timings of the round are set by the migration announce parameters.
45
An optional comma separated @var{interfaces} list restricts the announce to the
46
-named set of interfaces.
47
+named set of interfaces. An optional @var{id} can be used to start a separate announce
48
+timer and to change the parameters of it later.
49
ETEXI
50
51
{
52
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/monitor/hmp-cmds.c
55
+++ b/monitor/hmp-cmds.c
56
@@ -XXX,XX +XXX,XX @@ void hmp_info_snapshots(Monitor *mon, const QDict *qdict)
57
void hmp_announce_self(Monitor *mon, const QDict *qdict)
58
{
59
const char *interfaces_str = qdict_get_try_str(qdict, "interfaces");
60
+ const char *id = qdict_get_try_str(qdict, "id");
61
AnnounceParameters *params = QAPI_CLONE(AnnounceParameters,
62
migrate_announce_params());
63
64
qapi_free_strList(params->interfaces);
65
params->interfaces = strList_from_comma_list(interfaces_str);
66
params->has_interfaces = params->interfaces != NULL;
67
+ params->id = g_strdup(id);
68
+ params->has_id = !!params->id;
69
qmp_announce_self(params, NULL);
70
qapi_free_AnnounceParameters(params);
71
}
72
--
73
2.5.0
74
75
diff view generated by jsdifflib
Deleted patch
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
2
1
3
Expand self-announce test to check we can stop an announce timer.
4
We set it up to send 300 packets, but after we receive
5
the first one we tell it to stop.
6
7
We error if:
8
a) We receive more than 30 of the packets
9
b) We're still receiving packets after a lot longer than the
10
30 seconds should have arrived
11
12
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
13
Signed-off-by: Jason Wang <jasowang@redhat.com>
14
---
15
tests/virtio-net-test.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++---
16
1 file changed, 54 insertions(+), 3 deletions(-)
17
18
diff --git a/tests/virtio-net-test.c b/tests/virtio-net-test.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/tests/virtio-net-test.c
21
+++ b/tests/virtio-net-test.c
22
@@ -XXX,XX +XXX,XX @@ static void announce_self(void *obj, void *data, QGuestAllocator *t_alloc)
23
QDict *rsp;
24
int ret;
25
uint16_t *proto = (uint16_t *)&buffer[12];
26
+ size_t total_received = 0;
27
+ uint64_t start, now, last_rxt, deadline;
28
29
+ /* Send a set of packets over a few second period */
30
rsp = qmp("{ 'execute' : 'announce-self', "
31
" 'arguments': {"
32
- " 'initial': 50, 'max': 550,"
33
- " 'rounds': 10, 'step': 50 } }");
34
+ " 'initial': 20, 'max': 100,"
35
+ " 'rounds': 300, 'step': 10, 'id': 'bob' } }");
36
assert(!qdict_haskey(rsp, "error"));
37
qobject_unref(rsp);
38
39
- /* Catch the packet and make sure it's a RARP */
40
+ /* Catch the first packet and make sure it's a RARP */
41
ret = qemu_recv(sv[0], &len, sizeof(len), 0);
42
g_assert_cmpint(ret, ==, sizeof(len));
43
len = ntohl(len);
44
45
ret = qemu_recv(sv[0], buffer, len, 0);
46
g_assert_cmpint(*proto, ==, htons(ETH_P_RARP));
47
+
48
+ /*
49
+ * Stop the announcment by settings rounds to 0 on the
50
+ * existing timer.
51
+ */
52
+ rsp = qmp("{ 'execute' : 'announce-self', "
53
+ " 'arguments': {"
54
+ " 'initial': 20, 'max': 100,"
55
+ " 'rounds': 0, 'step': 10, 'id': 'bob' } }");
56
+ assert(!qdict_haskey(rsp, "error"));
57
+ qobject_unref(rsp);
58
+
59
+ /* Now make sure the packets stop */
60
+
61
+ /* Times are in us */
62
+ start = g_get_monotonic_time();
63
+ /* 30 packets, max gap 100ms, * 4 for wiggle */
64
+ deadline = start + 1000 * (100 * 30 * 4);
65
+ last_rxt = start;
66
+
67
+ while (true) {
68
+ int saved_err;
69
+ ret = qemu_recv(sv[0], buffer, 60, MSG_DONTWAIT);
70
+ saved_err = errno;
71
+ now = g_get_monotonic_time();
72
+ g_assert_cmpint(now, <, deadline);
73
+
74
+ if (ret >= 0) {
75
+ if (ret) {
76
+ last_rxt = now;
77
+ }
78
+ total_received += ret;
79
+
80
+ /* Check it's not spewing loads */
81
+ g_assert_cmpint(total_received, <, 60 * 30 * 2);
82
+ } else {
83
+ g_assert_cmpint(saved_err, ==, EAGAIN);
84
+
85
+ /* 400ms, i.e. 4 worst case gaps */
86
+ if ((now - last_rxt) > (1000 * 100 * 4)) {
87
+ /* Nothings arrived for a while - must have stopped */
88
+ break;
89
+ };
90
+
91
+ /* 100ms */
92
+ g_usleep(1000 * 100);
93
+ }
94
+ };
95
}
96
97
static void virtio_net_test_cleanup(void *sockets)
98
--
99
2.5.0
100
101
diff view generated by jsdifflib
1
From: Zhang Chen <chen.zhang@intel.com>
1
From: Eugenio Pérez <eperezma@redhat.com>
2
2
3
We need use this function to send notification message for remote colo-frame(Xen).
3
VHOST_BACKEND_F_IOTLB_ASID is the feature bit, not the bitmask. Since
4
So we add new parameter for this job.
4
the device under test also provided VHOST_BACKEND_F_IOTLB_MSG_V2 and
5
VHOST_BACKEND_F_IOTLB_BATCH, this went unnoticed.
5
6
6
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
7
Fixes: c1a1008685 ("vdpa: always start CVQ in SVQ mode if possible")
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>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
12
---
9
net/colo-compare.c | 41 +++++++++++++++++++++++++++++++++--------
13
net/vhost-vdpa.c | 2 +-
10
1 file changed, 33 insertions(+), 8 deletions(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
11
15
12
diff --git a/net/colo-compare.c b/net/colo-compare.c
16
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
13
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
14
--- a/net/colo-compare.c
18
--- a/net/vhost-vdpa.c
15
+++ b/net/colo-compare.c
19
+++ b/net/vhost-vdpa.c
16
@@ -XXX,XX +XXX,XX @@ static void colo_compare_inconsistency_notify(void)
20
@@ -XXX,XX +XXX,XX @@ static int vhost_vdpa_net_cvq_start(NetClientState *nc)
17
static int compare_chr_send(CompareState *s,
21
g_strerror(errno), errno);
18
const uint8_t *buf,
22
return -1;
19
uint32_t size,
20
- uint32_t vnet_hdr_len);
21
+ uint32_t vnet_hdr_len,
22
+ bool notify_remote_frame);
23
24
static gint seq_sorter(Packet *a, Packet *b, gpointer data)
25
{
26
@@ -XXX,XX +XXX,XX @@ static void colo_release_primary_pkt(CompareState *s, Packet *pkt)
27
ret = compare_chr_send(s,
28
pkt->data,
29
pkt->size,
30
- pkt->vnet_hdr_len);
31
+ pkt->vnet_hdr_len,
32
+ false);
33
if (ret < 0) {
34
error_report("colo send primary packet failed");
35
}
23
}
36
@@ -XXX,XX +XXX,XX @@ static void colo_compare_connection(void *opaque, void *user_data)
24
- if (!(backend_features & VHOST_BACKEND_F_IOTLB_ASID) ||
37
static int compare_chr_send(CompareState *s,
25
+ if (!(backend_features & BIT_ULL(VHOST_BACKEND_F_IOTLB_ASID)) ||
38
const uint8_t *buf,
26
!vhost_vdpa_net_valid_svq_features(v->dev->features, NULL)) {
39
uint32_t size,
40
- uint32_t vnet_hdr_len)
41
+ uint32_t vnet_hdr_len,
42
+ bool notify_remote_frame)
43
{
44
int ret = 0;
45
uint32_t len = htonl(size);
46
@@ -XXX,XX +XXX,XX @@ static int compare_chr_send(CompareState *s,
47
return 0;
27
return 0;
48
}
28
}
49
50
- ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len));
51
+ if (notify_remote_frame) {
52
+ ret = qemu_chr_fe_write_all(&s->chr_notify_dev,
53
+ (uint8_t *)&len,
54
+ sizeof(len));
55
+ } else {
56
+ ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len));
57
+ }
58
+
59
if (ret != sizeof(len)) {
60
goto err;
61
}
62
@@ -XXX,XX +XXX,XX @@ static int compare_chr_send(CompareState *s,
63
* know how to parse net packet correctly.
64
*/
65
len = htonl(vnet_hdr_len);
66
- ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len));
67
+
68
+ if (!notify_remote_frame) {
69
+ ret = qemu_chr_fe_write_all(&s->chr_out,
70
+ (uint8_t *)&len,
71
+ sizeof(len));
72
+ }
73
+
74
if (ret != sizeof(len)) {
75
goto err;
76
}
77
}
78
79
- ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)buf, size);
80
+ if (notify_remote_frame) {
81
+ ret = qemu_chr_fe_write_all(&s->chr_notify_dev,
82
+ (uint8_t *)buf,
83
+ size);
84
+ } else {
85
+ ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)buf, size);
86
+ }
87
+
88
if (ret != size) {
89
goto err;
90
}
91
@@ -XXX,XX +XXX,XX @@ static void compare_pri_rs_finalize(SocketReadState *pri_rs)
92
compare_chr_send(s,
93
pri_rs->buf,
94
pri_rs->packet_len,
95
- pri_rs->vnet_hdr_len);
96
+ pri_rs->vnet_hdr_len,
97
+ false);
98
} else {
99
/* compare packet in the specified connection */
100
colo_compare_connection(conn, s);
101
@@ -XXX,XX +XXX,XX @@ static void colo_flush_packets(void *opaque, void *user_data)
102
compare_chr_send(s,
103
pkt->data,
104
pkt->size,
105
- pkt->vnet_hdr_len);
106
+ pkt->vnet_hdr_len,
107
+ false);
108
packet_destroy(pkt, NULL);
109
}
110
while (!g_queue_is_empty(&conn->secondary_list)) {
111
--
29
--
112
2.5.0
30
2.7.4
113
31
114
32
diff view generated by jsdifflib