1
The following changes since commit a73549f99612f758dec0fdea6ae1c30b6c709a0b:
1
The following changes since commit f8d75e10d3e0033a0a29a7a7e4777a4fbc17a016:
2
2
3
Merge remote-tracking branch 'remotes/kraxel/tags/ui-20181012-pull-request' into staging (2018-10-12 16:45:51 +0100)
3
Merge remote-tracking branch 'remotes/legoater/tags/pull-ppc-20220112' into staging (2022-01-13 11:18:24 +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 a7ec0077c2db445d6bae421963188367d2695bd6:
9
for you to fetch changes up to 818692f0a01587d02220916b31d5bb8e7dced611:
10
10
11
qemu-options: Fix bad "macaddr" property in the documentation (2018-10-15 16:14:15 +0800)
11
net/vmnet: update MAINTAINERS list (2022-01-14 12:58:19 +0800)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
14
15
Changes since V2:
16
17
- Try to make vmnet work on some old mac version
18
15
----------------------------------------------------------------
19
----------------------------------------------------------------
16
Jason Wang (4):
20
Peter Foley (2):
17
ne2000: fix possible out of bound access in ne2000_receive
21
net/tap: Set return code on failure
18
rtl8139: fix possible out of bound access
22
net: Fix uninitialized data usage
19
pcnet: fix possible buffer overflow
20
net: ignore packet size greater than INT_MAX
21
23
22
Martin Wilck (1):
24
Philippe Mathieu-Daudé (1):
23
e1000: indicate dropped packets in HW counters
25
hw/net/vmxnet3: Log guest-triggerable errors using LOG_GUEST_ERROR
24
26
25
Thomas Huth (1):
27
Rao Lei (1):
26
qemu-options: Fix bad "macaddr" property in the documentation
28
net/filter: Optimize filter_send to coroutine
27
29
28
Zhang Chen (15):
30
Vladislav Yaroshchuk (7):
29
filter-rewriter: Add TCP state machine and fix memory leak in connection_track_table
31
net/vmnet: add vmnet dependency and customizable option
30
colo-compare: implement the process of checkpoint
32
net/vmnet: add vmnet backends to qapi/net
31
colo-compare: use notifier to notify packets comparing result
33
net/vmnet: implement shared mode (vmnet-shared)
32
1;5202;0c1;5202;0c COLO: integrate colo compare with colo frame
34
net/vmnet: implement host mode (vmnet-host)
33
COLO: Add block replication into colo process
35
net/vmnet: implement bridged mode (vmnet-bridged)
34
COLO: Remove colo_state migration struct
36
net/vmnet: update qemu-options.hx
35
COLO: Load dirty pages into SVM's RAM cache firstly
37
net/vmnet: update MAINTAINERS list
36
ram/COLO: Record the dirty pages that SVM received
37
COLO: Flush memory data from ram cache
38
qapi/migration.json: Rename COLO unknown mode to none mode.
39
qapi: Add new command to query colo status
40
savevm: split the process of different stages for loadvm/savevm
41
filter: Add handle_event method for NetFilterClass
42
filter-rewriter: handle checkpoint and failover event
43
docs: Add COLO status diagram to COLO-FT.txt
44
38
45
liujunjie (1):
39
Zhang Chen (2):
46
clean up callback when del virtqueue
40
net/colo-compare.c: Optimize compare order for performance
41
net/colo-compare.c: Update the default value comments
47
42
48
zhanghailiang (4):
43
MAINTAINERS | 5 +
49
qmp event: Add COLO_EXIT event to notify users while exited COLO
44
hw/net/vmxnet3.c | 4 +-
50
COLO: flush host dirty ram from cache
45
meson.build | 16 +-
51
COLO: notify net filters about checkpoint/failover event
46
meson_options.txt | 2 +
52
COLO: quick failover process by kick COLO thread
47
net/clients.h | 11 ++
53
48
net/colo-compare.c | 28 ++--
54
docs/COLO-FT.txt | 34 ++++++++
49
net/filter-mirror.c | 66 +++++++--
55
hw/net/e1000.c | 16 +++-
50
net/meson.build | 7 +
56
hw/net/ne2000.c | 4 +-
51
net/net.c | 10 ++
57
hw/net/pcnet.c | 4 +-
52
net/tap-linux.c | 1 +
58
hw/net/rtl8139.c | 8 +-
53
net/tap.c | 1 +
59
hw/net/trace-events | 3 +
54
net/vmnet-bridged.m | 120 +++++++++++++++
60
hw/virtio/virtio.c | 2 +
55
net/vmnet-common.m | 333 ++++++++++++++++++++++++++++++++++++++++++
61
include/exec/ram_addr.h | 1 +
56
net/vmnet-host.c | 122 ++++++++++++++++
62
include/migration/colo.h | 11 ++-
57
net/vmnet-shared.c | 100 +++++++++++++
63
include/net/filter.h | 5 ++
58
net/vmnet_int.h | 48 ++++++
64
migration/Makefile.objs | 2 +-
59
qapi/net.json | 133 ++++++++++++++++-
65
migration/colo-comm.c | 76 -----------------
60
qemu-options.hx | 25 ++++
66
migration/colo-failover.c | 2 +-
61
scripts/meson-buildoptions.sh | 3 +
67
migration/colo.c | 212 +++++++++++++++++++++++++++++++++++++++++++---
62
19 files changed, 1004 insertions(+), 31 deletions(-)
68
migration/migration.c | 46 ++++++++--
63
create mode 100644 net/vmnet-bridged.m
69
migration/ram.c | 166 +++++++++++++++++++++++++++++++++++-
64
create mode 100644 net/vmnet-common.m
70
migration/ram.h | 4 +
65
create mode 100644 net/vmnet-host.c
71
migration/savevm.c | 53 ++++++++++--
66
create mode 100644 net/vmnet-shared.c
72
migration/savevm.h | 5 ++
67
create mode 100644 net/vmnet_int.h
73
migration/trace-events | 3 +
74
net/colo-compare.c | 115 ++++++++++++++++++++++---
75
net/colo-compare.h | 24 ++++++
76
net/colo.c | 10 ++-
77
net/colo.h | 11 +--
78
net/filter-rewriter.c | 166 +++++++++++++++++++++++++++++++++---
79
net/filter.c | 17 ++++
80
net/net.c | 26 +++++-
81
qapi/migration.json | 80 +++++++++++++++--
82
qemu-options.hx | 2 +-
83
vl.c | 2 -
84
30 files changed, 958 insertions(+), 152 deletions(-)
85
delete mode 100644 migration/colo-comm.c
86
create mode 100644 net/colo-compare.h
87
68
88
69
89
diff view generated by jsdifflib
Deleted patch
1
From: Zhang Chen <zhangckid@gmail.com>
2
1
3
We add almost full TCP state machine in filter-rewriter, except
4
TCPS_LISTEN and some simplify in VM active close FIN states.
5
The reason for this simplify job is because guest kernel will track
6
the TCP status and wait 2MSL time too, if client resend the FIN packet,
7
guest will resend the last ACK, so we needn't wait 2MSL time in filter-rewriter.
8
9
After a net connection is closed, we didn't clear its related resources
10
in connection_track_table, which will lead to memory leak.
11
12
Let's track the state of net connection, if it is closed, its related
13
resources will be cleared up.
14
15
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
16
Signed-off-by: Zhang Chen <zhangckid@gmail.com>
17
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
18
Signed-off-by: Jason Wang <jasowang@redhat.com>
19
---
20
net/colo.c | 2 +-
21
net/colo.h | 9 ++---
22
net/filter-rewriter.c | 109 +++++++++++++++++++++++++++++++++++++++++++++-----
23
3 files changed, 104 insertions(+), 16 deletions(-)
24
25
diff --git a/net/colo.c b/net/colo.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/net/colo.c
28
+++ b/net/colo.c
29
@@ -XXX,XX +XXX,XX @@ Connection *connection_new(ConnectionKey *key)
30
conn->ip_proto = key->ip_proto;
31
conn->processing = false;
32
conn->offset = 0;
33
- conn->syn_flag = 0;
34
+ conn->tcp_state = TCPS_CLOSED;
35
conn->pack = 0;
36
conn->sack = 0;
37
g_queue_init(&conn->primary_list);
38
diff --git a/net/colo.h b/net/colo.h
39
index XXXXXXX..XXXXXXX 100644
40
--- a/net/colo.h
41
+++ b/net/colo.h
42
@@ -XXX,XX +XXX,XX @@
43
#include "slirp/slirp.h"
44
#include "qemu/jhash.h"
45
#include "qemu/timer.h"
46
+#include "slirp/tcp.h"
47
48
#define HASHTABLE_MAX_SIZE 16384
49
50
@@ -XXX,XX +XXX,XX @@ typedef struct Connection {
51
uint32_t sack;
52
/* offset = secondary_seq - primary_seq */
53
tcp_seq offset;
54
- /*
55
- * we use this flag update offset func
56
- * run once in independent tcp connection
57
- */
58
- int syn_flag;
59
+
60
+ int tcp_state; /* TCP FSM state */
61
+ tcp_seq fin_ack_seq; /* the seq of 'fin=1,ack=1' */
62
} Connection;
63
64
uint32_t connection_key_hash(const void *opaque);
65
diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/net/filter-rewriter.c
68
+++ b/net/filter-rewriter.c
69
@@ -XXX,XX +XXX,XX @@ static int is_tcp_packet(Packet *pkt)
70
}
71
72
/* handle tcp packet from primary guest */
73
-static int handle_primary_tcp_pkt(NetFilterState *nf,
74
+static int handle_primary_tcp_pkt(RewriterState *rf,
75
Connection *conn,
76
- Packet *pkt)
77
+ Packet *pkt, ConnectionKey *key)
78
{
79
struct tcphdr *tcp_pkt;
80
81
@@ -XXX,XX +XXX,XX @@ static int handle_primary_tcp_pkt(NetFilterState *nf,
82
trace_colo_filter_rewriter_conn_offset(conn->offset);
83
}
84
85
+ if (((tcp_pkt->th_flags & (TH_ACK | TH_SYN)) == (TH_ACK | TH_SYN)) &&
86
+ conn->tcp_state == TCPS_SYN_SENT) {
87
+ conn->tcp_state = TCPS_ESTABLISHED;
88
+ }
89
+
90
if (((tcp_pkt->th_flags & (TH_ACK | TH_SYN)) == TH_SYN)) {
91
/*
92
* we use this flag update offset func
93
* run once in independent tcp connection
94
*/
95
- conn->syn_flag = 1;
96
+ conn->tcp_state = TCPS_SYN_RECEIVED;
97
}
98
99
if (((tcp_pkt->th_flags & (TH_ACK | TH_SYN)) == TH_ACK)) {
100
- if (conn->syn_flag) {
101
+ if (conn->tcp_state == TCPS_SYN_RECEIVED) {
102
/*
103
* offset = secondary_seq - primary seq
104
* ack packet sent by guest from primary node,
105
* so we use th_ack - 1 get primary_seq
106
*/
107
conn->offset -= (ntohl(tcp_pkt->th_ack) - 1);
108
- conn->syn_flag = 0;
109
+ conn->tcp_state = TCPS_ESTABLISHED;
110
}
111
if (conn->offset) {
112
/* handle packets to the secondary from the primary */
113
@@ -XXX,XX +XXX,XX @@ static int handle_primary_tcp_pkt(NetFilterState *nf,
114
net_checksum_calculate((uint8_t *)pkt->data + pkt->vnet_hdr_len,
115
pkt->size - pkt->vnet_hdr_len);
116
}
117
+
118
+ /*
119
+ * Passive close step 3
120
+ */
121
+ if ((conn->tcp_state == TCPS_LAST_ACK) &&
122
+ (ntohl(tcp_pkt->th_ack) == (conn->fin_ack_seq + 1))) {
123
+ conn->tcp_state = TCPS_CLOSED;
124
+ g_hash_table_remove(rf->connection_track_table, key);
125
+ }
126
+ }
127
+
128
+ if ((tcp_pkt->th_flags & TH_FIN) == TH_FIN) {
129
+ /*
130
+ * Passive close.
131
+ * Step 1:
132
+ * The *server* side of this connect is VM, *client* tries to close
133
+ * the connection. We will into CLOSE_WAIT status.
134
+ *
135
+ * Step 2:
136
+ * In this step we will into LAST_ACK status.
137
+ *
138
+ * We got 'fin=1, ack=1' packet from server side, we need to
139
+ * record the seq of 'fin=1, ack=1' packet.
140
+ *
141
+ * Step 3:
142
+ * We got 'ack=1' packets from client side, it acks 'fin=1, ack=1'
143
+ * packet from server side. From this point, we can ensure that there
144
+ * will be no packets in the connection, except that, some errors
145
+ * happen between the path of 'filter object' and vNIC, if this rare
146
+ * case really happen, we can still create a new connection,
147
+ * So it is safe to remove the connection from connection_track_table.
148
+ *
149
+ */
150
+ if (conn->tcp_state == TCPS_ESTABLISHED) {
151
+ conn->tcp_state = TCPS_CLOSE_WAIT;
152
+ }
153
+
154
+ /*
155
+ * Active close step 2.
156
+ */
157
+ if (conn->tcp_state == TCPS_FIN_WAIT_1) {
158
+ conn->tcp_state = TCPS_TIME_WAIT;
159
+ /*
160
+ * For simplify implementation, we needn't wait 2MSL time
161
+ * in filter rewriter. Because guest kernel will track the
162
+ * TCP status and wait 2MSL time, if client resend the FIN
163
+ * packet, guest will apply the last ACK too.
164
+ */
165
+ conn->tcp_state = TCPS_CLOSED;
166
+ g_hash_table_remove(rf->connection_track_table, key);
167
+ }
168
}
169
170
return 0;
171
}
172
173
/* handle tcp packet from secondary guest */
174
-static int handle_secondary_tcp_pkt(NetFilterState *nf,
175
+static int handle_secondary_tcp_pkt(RewriterState *rf,
176
Connection *conn,
177
- Packet *pkt)
178
+ Packet *pkt, ConnectionKey *key)
179
{
180
struct tcphdr *tcp_pkt;
181
182
@@ -XXX,XX +XXX,XX @@ static int handle_secondary_tcp_pkt(NetFilterState *nf,
183
trace_colo_filter_rewriter_conn_offset(conn->offset);
184
}
185
186
- if (((tcp_pkt->th_flags & (TH_ACK | TH_SYN)) == (TH_ACK | TH_SYN))) {
187
+ if (conn->tcp_state == TCPS_SYN_RECEIVED &&
188
+ ((tcp_pkt->th_flags & (TH_ACK | TH_SYN)) == (TH_ACK | TH_SYN))) {
189
/*
190
* save offset = secondary_seq and then
191
* in handle_primary_tcp_pkt make offset
192
@@ -XXX,XX +XXX,XX @@ static int handle_secondary_tcp_pkt(NetFilterState *nf,
193
conn->offset = ntohl(tcp_pkt->th_seq);
194
}
195
196
+ /* VM active connect */
197
+ if (conn->tcp_state == TCPS_CLOSED &&
198
+ ((tcp_pkt->th_flags & (TH_ACK | TH_SYN)) == TH_SYN)) {
199
+ conn->tcp_state = TCPS_SYN_SENT;
200
+ }
201
+
202
if ((tcp_pkt->th_flags & (TH_ACK | TH_SYN)) == TH_ACK) {
203
/* Only need to adjust seq while offset is Non-zero */
204
if (conn->offset) {
205
@@ -XXX,XX +XXX,XX @@ static int handle_secondary_tcp_pkt(NetFilterState *nf,
206
}
207
}
208
209
+ /*
210
+ * Passive close step 2:
211
+ */
212
+ if (conn->tcp_state == TCPS_CLOSE_WAIT &&
213
+ (tcp_pkt->th_flags & (TH_ACK | TH_FIN)) == (TH_ACK | TH_FIN)) {
214
+ conn->fin_ack_seq = ntohl(tcp_pkt->th_seq);
215
+ conn->tcp_state = TCPS_LAST_ACK;
216
+ }
217
+
218
+ /*
219
+ * Active close
220
+ *
221
+ * Step 1:
222
+ * The *server* side of this connect is VM, *server* tries to close
223
+ * the connection.
224
+ *
225
+ * Step 2:
226
+ * We will into CLOSE_WAIT status.
227
+ * We simplify the TCPS_FIN_WAIT_2, TCPS_TIME_WAIT and
228
+ * CLOSING status.
229
+ */
230
+ if (conn->tcp_state == TCPS_ESTABLISHED &&
231
+ (tcp_pkt->th_flags & (TH_ACK | TH_FIN)) == TH_FIN) {
232
+ conn->tcp_state = TCPS_FIN_WAIT_1;
233
+ }
234
+
235
return 0;
236
}
237
238
@@ -XXX,XX +XXX,XX @@ static ssize_t colo_rewriter_receive_iov(NetFilterState *nf,
239
240
if (sender == nf->netdev) {
241
/* NET_FILTER_DIRECTION_TX */
242
- if (!handle_primary_tcp_pkt(nf, conn, pkt)) {
243
+ if (!handle_primary_tcp_pkt(s, conn, pkt, &key)) {
244
qemu_net_queue_send(s->incoming_queue, sender, 0,
245
(const uint8_t *)pkt->data, pkt->size, NULL);
246
packet_destroy(pkt, NULL);
247
@@ -XXX,XX +XXX,XX @@ static ssize_t colo_rewriter_receive_iov(NetFilterState *nf,
248
}
249
} else {
250
/* NET_FILTER_DIRECTION_RX */
251
- if (!handle_secondary_tcp_pkt(nf, conn, pkt)) {
252
+ if (!handle_secondary_tcp_pkt(s, conn, pkt, &key)) {
253
qemu_net_queue_send(s->incoming_queue, sender, 0,
254
(const uint8_t *)pkt->data, pkt->size, NULL);
255
packet_destroy(pkt, NULL);
256
--
257
2.5.0
258
259
diff view generated by jsdifflib
1
From: Martin Wilck <mwilck@suse.com>
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
2
3
The e1000 emulation silently discards RX packets if there's
3
The "Interrupt Cause" register (VMXNET3_REG_ICR) is read-only.
4
insufficient space in the ring buffer. This leads to errors
4
Write accesses are ignored. Log them with as LOG_GUEST_ERROR
5
on higher-level protocols in the guest, with no indication
5
instead of aborting:
6
about the error cause.
7
6
8
This patch increments the "Missed Packets Count" (MPC) and
7
[R +0.239743] writeq 0xe0002031 0x46291a5a55460800
9
"Receive No Buffers Count" (RNBC) HW counters in this case.
8
ERROR:hw/net/vmxnet3.c:1819:vmxnet3_io_bar1_write: code should not be reached
10
As the emulation has no FIFO for buffering packets that can't
9
Thread 1 "qemu-system-i38" received signal SIGABRT, Aborted.
11
immediately be pushed to the guest, these two registers are
10
(gdb) bt
12
practically equivalent (see 10.2.7.4, 10.2.7.33 in
11
#3 0x74c397d3 in __GI_abort () at abort.c:79
13
https://www.intel.com/content/www/us/en/embedded/products/networking/82574l-gbe-controller-datasheet.html).
12
#4 0x76d3cd4c in g_assertion_message (domain=<optimized out>, file=<optimized out>, line=<optimized out>, func=<optimized out>, message=<optimized out>) at ../glib/gtestutils.c:3223
13
#5 0x76d9d45f in g_assertion_message_expr
14
(domain=0x0, file=0x59fc2e53 "hw/net/vmxnet3.c", line=1819, func=0x59fc11e0 <__func__.vmxnet3_io_bar1_write> "vmxnet3_io_bar1_write", expr=<optimized out>)
15
at ../glib/gtestutils.c:3249
16
#6 0x57e80a3a in vmxnet3_io_bar1_write (opaque=0x62814100, addr=56, val=70, size=4) at hw/net/vmxnet3.c:1819
17
#7 0x58c2d894 in memory_region_write_accessor (mr=0x62816b90, addr=56, value=0x7fff9450, size=4, shift=0, mask=4294967295, attrs=...) at softmmu/memory.c:492
18
#8 0x58c2d1d2 in access_with_adjusted_size (addr=56, value=0x7fff9450, size=1, access_size_min=4, access_size_max=4, access_fn=
19
0x58c2d290 <memory_region_write_accessor>, mr=0x62816b90, attrs=...) at softmmu/memory.c:554
20
#9 0x58c2bae7 in memory_region_dispatch_write (mr=0x62816b90, addr=56, data=70, op=MO_8, attrs=...) at softmmu/memory.c:1504
21
#10 0x58bfd034 in flatview_write_continue (fv=0x606000181700, addr=0xe0002038, attrs=..., ptr=0x7fffb9e0, len=1, addr1=56, l=1, mr=0x62816b90)
22
at softmmu/physmem.c:2782
23
#11 0x58beba00 in flatview_write (fv=0x606000181700, addr=0xe0002031, attrs=..., buf=0x7fffb9e0, len=8) at softmmu/physmem.c:2822
24
#12 0x58beb589 in address_space_write (as=0x608000015f20, addr=0xe0002031, attrs=..., buf=0x7fffb9e0, len=8) at softmmu/physmem.c:2914
14
25
15
On a Linux guest, the register content will be reflected in
26
Reported-by: Dike <dike199774@qq.com>
16
the "rx_missed_errors" and "rx_no_buffer_count" stats from
27
Reported-by: Duhao <504224090@qq.com>
17
"ethtool -S", and in the "missed" stat from "ip -s -s link show",
28
BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=2032932
18
giving at least some hint about the error cause inside the guest.
29
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
19
20
If the cause is known, problems like this can often be avoided
21
easily, by increasing the number of RX descriptors in the guest
22
e1000 driver (e.g under Linux, "e1000.RxDescriptors=1024").
23
24
The patch also adds a qemu trace message for this condition.
25
26
Signed-off-by: Martin Wilck <mwilck@suse.com>
27
Signed-off-by: Jason Wang <jasowang@redhat.com>
30
Signed-off-by: Jason Wang <jasowang@redhat.com>
28
---
31
---
29
hw/net/e1000.c | 16 +++++++++++++---
32
hw/net/vmxnet3.c | 4 +++-
30
hw/net/trace-events | 3 +++
33
1 file changed, 3 insertions(+), 1 deletion(-)
31
2 files changed, 16 insertions(+), 3 deletions(-)
32
34
33
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
35
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
34
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/net/e1000.c
37
--- a/hw/net/vmxnet3.c
36
+++ b/hw/net/e1000.c
38
+++ b/hw/net/vmxnet3.c
37
@@ -XXX,XX +XXX,XX @@
39
@@ -XXX,XX +XXX,XX @@ vmxnet3_io_bar1_write(void *opaque,
38
#include "qemu/range.h"
40
case VMXNET3_REG_ICR:
39
41
VMW_CBPRN("Write BAR1 [VMXNET3_REG_ICR] = %" PRIx64 ", size %d",
40
#include "e1000x_common.h"
42
val, size);
41
+#include "trace.h"
43
- g_assert_not_reached();
42
44
+ qemu_log_mask(LOG_GUEST_ERROR,
43
static const uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
45
+ "%s: write to read-only register VMXNET3_REG_ICR\n",
44
46
+ TYPE_VMXNET3);
45
@@ -XXX,XX +XXX,XX @@ static uint64_t rx_desc_base(E1000State *s)
47
break;
46
return (bah << 32) + bal;
48
47
}
49
/* Event Cause Register */
48
49
+static void
50
+e1000_receiver_overrun(E1000State *s, size_t size)
51
+{
52
+ trace_e1000_receiver_overrun(size, s->mac_reg[RDH], s->mac_reg[RDT]);
53
+ e1000x_inc_reg_if_not_full(s->mac_reg, RNBC);
54
+ e1000x_inc_reg_if_not_full(s->mac_reg, MPC);
55
+ set_ics(s, 0, E1000_ICS_RXO);
56
+}
57
+
58
static ssize_t
59
e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt)
60
{
61
@@ -XXX,XX +XXX,XX @@ e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt)
62
desc_offset = 0;
63
total_size = size + e1000x_fcs_len(s->mac_reg);
64
if (!e1000_has_rxbufs(s, total_size)) {
65
- set_ics(s, 0, E1000_ICS_RXO);
66
- return -1;
67
+ e1000_receiver_overrun(s, total_size);
68
+ return -1;
69
}
70
do {
71
desc_size = total_size - desc_offset;
72
@@ -XXX,XX +XXX,XX @@ e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt)
73
rdh_start >= s->mac_reg[RDLEN] / sizeof(desc)) {
74
DBGOUT(RXERR, "RDH wraparound @%x, RDT %x, RDLEN %x\n",
75
rdh_start, s->mac_reg[RDT], s->mac_reg[RDLEN]);
76
- set_ics(s, 0, E1000_ICS_RXO);
77
+ e1000_receiver_overrun(s, total_size);
78
return -1;
79
}
80
} while (desc_offset < total_size);
81
diff --git a/hw/net/trace-events b/hw/net/trace-events
82
index XXXXXXX..XXXXXXX 100644
83
--- a/hw/net/trace-events
84
+++ b/hw/net/trace-events
85
@@ -XXX,XX +XXX,XX @@ net_rx_pkt_rss_ip6_ex(void) "Calculating IPv6/EX RSS hash"
86
net_rx_pkt_rss_hash(size_t rss_length, uint32_t rss_hash) "RSS hash for %zu bytes: 0x%X"
87
net_rx_pkt_rss_add_chunk(void* ptr, size_t size, size_t input_offset) "Add RSS chunk %p, %zu bytes, RSS input offset %zu bytes"
88
89
+# hw/net/e1000.c
90
+e1000_receiver_overrun(size_t s, uint32_t rdh, uint32_t rdt) "Receiver overrun: dropped packet of %lu bytes, RDH=%u, RDT=%u"
91
+
92
# hw/net/e1000x_common.c
93
e1000x_rx_can_recv_disabled(bool link_up, bool rx_enabled, bool pci_master) "link_up: %d, rx_enabled %d, pci_master %d"
94
e1000x_vlan_is_vlan_pkt(bool is_vlan_pkt, uint16_t eth_proto, uint16_t vet) "Is VLAN packet: %d, ETH proto: 0x%X, VET: 0x%X"
95
--
50
--
96
2.5.0
51
2.7.4
97
52
98
53
diff view generated by jsdifflib
1
There should not be a reason for passing a packet size greater than
1
From: Peter Foley <pefoley@google.com>
2
INT_MAX. It's usually a hint of bug somewhere, so ignore packet size
3
greater than INT_MAX in qemu_deliver_packet_iov()
4
2
5
CC: qemu-stable@nongnu.org
3
Match the other error handling in this function.
6
Reported-by: Daniel Shapira <daniel@twistlock.com>
4
7
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
5
Fixes: e7b347d0bf6 ("net: detect errors from probing vnet hdr flag for TAP devices")
6
7
Reviewed-by: Patrick Venture <venture@google.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Signed-off-by: Peter Foley <pefoley@google.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
11
---
10
net/net.c | 7 ++++++-
12
net/tap.c | 1 +
11
1 file changed, 6 insertions(+), 1 deletion(-)
13
1 file changed, 1 insertion(+)
12
14
13
diff --git a/net/net.c b/net/net.c
15
diff --git a/net/tap.c b/net/tap.c
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/net/net.c
17
--- a/net/tap.c
16
+++ b/net/net.c
18
+++ b/net/tap.c
17
@@ -XXX,XX +XXX,XX @@ ssize_t qemu_deliver_packet_iov(NetClientState *sender,
19
@@ -XXX,XX +XXX,XX @@ int net_init_tap(const Netdev *netdev, const char *name,
18
void *opaque)
20
if (i == 0) {
19
{
21
vnet_hdr = tap_probe_vnet_hdr(fd, errp);
20
NetClientState *nc = opaque;
22
if (vnet_hdr < 0) {
21
+ size_t size = iov_size(iov, iovcnt);
23
+ ret = -1;
22
int ret;
24
goto free_fail;
23
25
}
24
+ if (size > INT_MAX) {
26
} else if (vnet_hdr != tap_probe_vnet_hdr(fd, NULL)) {
25
+ return size;
26
+ }
27
+
28
if (nc->link_down) {
29
- return iov_size(iov, iovcnt);
30
+ return size;
31
}
32
33
if (nc->receive_disabled) {
34
--
27
--
35
2.5.0
28
2.7.4
36
29
37
30
diff view generated by jsdifflib
1
In pcnet_receive(), we try to assign size_ to size which converts from
1
From: Peter Foley <pefoley@google.com>
2
size_t to integer. This will cause troubles when size_ is greater
3
INT_MAX, this will lead a negative value in size and it can then pass
4
the check of size < MIN_BUF_SIZE which may lead out of bound access
5
for both buf and buf1.
6
2
7
Fixing by converting the type of size to size_t.
3
e.g.
4
1109 15:16:20.151506 Uninitialized bytes in ioctl_common_pre at offset 0 inside [0x7ffc516af9b8, 4)
5
1109 15:16:20.151659 ==588974==WARNING: MemorySanitizer: use-of-uninitialized-value
6
1109 15:16:20.312923 #0 0x5639b88acb21 in tap_probe_vnet_hdr_len third_party/qemu/net/tap-linux.c:183:9
7
1109 15:16:20.312952 #1 0x5639b88afd66 in net_tap_fd_init third_party/qemu/net/tap.c:409:9
8
1109 15:16:20.312954 #2 0x5639b88b2d1b in net_init_tap_one third_party/qemu/net/tap.c:681:19
9
1109 15:16:20.312956 #3 0x5639b88b16a8 in net_init_tap third_party/qemu/net/tap.c:912:13
10
1109 15:16:20.312957 #4 0x5639b8890175 in net_client_init1 third_party/qemu/net/net.c:1110:9
11
1109 15:16:20.312958 #5 0x5639b888f912 in net_client_init third_party/qemu/net/net.c:1208:15
12
1109 15:16:20.312960 #6 0x5639b8894aa5 in net_param_nic third_party/qemu/net/net.c:1588:11
13
1109 15:16:20.312961 #7 0x5639b900cd18 in qemu_opts_foreach third_party/qemu/util/qemu-option.c:1135:14
14
1109 15:16:20.312962 #8 0x5639b889393c in net_init_clients third_party/qemu/net/net.c:1612:9
15
1109 15:16:20.312964 #9 0x5639b717aaf3 in qemu_create_late_backends third_party/qemu/softmmu/vl.c:1962:5
16
1109 15:16:20.312965 #10 0x5639b717aaf3 in qemu_init third_party/qemu/softmmu/vl.c:3694:5
17
1109 15:16:20.312967 #11 0x5639b71083b8 in main third_party/qemu/softmmu/main.c:49:5
18
1109 15:16:20.312968 #12 0x7f464de1d8d2 in __libc_start_main (/usr/grte/v5/lib64/libc.so.6+0x628d2)
19
1109 15:16:20.312969 #13 0x5639b6bbd389 in _start /usr/grte/v5/debug-src/src/csu/../sysdeps/x86_64/start.S:120
20
1109 15:16:20.312970
21
1109 15:16:20.312975 Uninitialized value was stored to memory at
22
1109 15:16:20.313393 #0 0x5639b88acbee in tap_probe_vnet_hdr_len third_party/qemu/net/tap-linux.c
23
1109 15:16:20.313396 #1 0x5639b88afd66 in net_tap_fd_init third_party/qemu/net/tap.c:409:9
24
1109 15:16:20.313398 #2 0x5639b88b2d1b in net_init_tap_one third_party/qemu/net/tap.c:681:19
25
1109 15:16:20.313399 #3 0x5639b88b16a8 in net_init_tap third_party/qemu/net/tap.c:912:13
26
1109 15:16:20.313400 #4 0x5639b8890175 in net_client_init1 third_party/qemu/net/net.c:1110:9
27
1109 15:16:20.313401 #5 0x5639b888f912 in net_client_init third_party/qemu/net/net.c:1208:15
28
1109 15:16:20.313403 #6 0x5639b8894aa5 in net_param_nic third_party/qemu/net/net.c:1588:11
29
1109 15:16:20.313404 #7 0x5639b900cd18 in qemu_opts_foreach third_party/qemu/util/qemu-option.c:1135:14
30
1109 15:16:20.313405 #8 0x5639b889393c in net_init_clients third_party/qemu/net/net.c:1612:9
31
1109 15:16:20.313407 #9 0x5639b717aaf3 in qemu_create_late_backends third_party/qemu/softmmu/vl.c:1962:5
32
1109 15:16:20.313408 #10 0x5639b717aaf3 in qemu_init third_party/qemu/softmmu/vl.c:3694:5
33
1109 15:16:20.313409 #11 0x5639b71083b8 in main third_party/qemu/softmmu/main.c:49:5
34
1109 15:16:20.313410 #12 0x7f464de1d8d2 in __libc_start_main (/usr/grte/v5/lib64/libc.so.6+0x628d2)
35
1109 15:16:20.313412 #13 0x5639b6bbd389 in _start /usr/grte/v5/debug-src/src/csu/../sysdeps/x86_64/start.S:120
36
1109 15:16:20.313413
37
1109 15:16:20.313417 Uninitialized value was stored to memory at
38
1109 15:16:20.313791 #0 0x5639b88affbd in net_tap_fd_init third_party/qemu/net/tap.c:400:26
39
1109 15:16:20.313826 #1 0x5639b88b2d1b in net_init_tap_one third_party/qemu/net/tap.c:681:19
40
1109 15:16:20.313829 #2 0x5639b88b16a8 in net_init_tap third_party/qemu/net/tap.c:912:13
41
1109 15:16:20.313831 #3 0x5639b8890175 in net_client_init1 third_party/qemu/net/net.c:1110:9
42
1109 15:16:20.313836 #4 0x5639b888f912 in net_client_init third_party/qemu/net/net.c:1208:15
43
1109 15:16:20.313838 #5 0x5639b8894aa5 in net_param_nic third_party/qemu/net/net.c:1588:11
44
1109 15:16:20.313839 #6 0x5639b900cd18 in qemu_opts_foreach third_party/qemu/util/qemu-option.c:1135:14
45
1109 15:16:20.313841 #7 0x5639b889393c in net_init_clients third_party/qemu/net/net.c:1612:9
46
1109 15:16:20.313843 #8 0x5639b717aaf3 in qemu_create_late_backends third_party/qemu/softmmu/vl.c:1962:5
47
1109 15:16:20.313844 #9 0x5639b717aaf3 in qemu_init third_party/qemu/softmmu/vl.c:3694:5
48
1109 15:16:20.313845 #10 0x5639b71083b8 in main third_party/qemu/softmmu/main.c:49:5
49
1109 15:16:20.313846 #11 0x7f464de1d8d2 in __libc_start_main (/usr/grte/v5/lib64/libc.so.6+0x628d2)
50
1109 15:16:20.313847 #12 0x5639b6bbd389 in _start /usr/grte/v5/debug-src/src/csu/../sysdeps/x86_64/start.S:120
51
1109 15:16:20.313849
52
1109 15:16:20.313851 Uninitialized value was created by an allocation of 'ifr' in the stack frame of function 'tap_probe_vnet_hdr'
53
1109 15:16:20.313855 #0 0x5639b88ac680 in tap_probe_vnet_hdr third_party/qemu/net/tap-linux.c:151
54
1109 15:16:20.313856
55
1109 15:16:20.313878 SUMMARY: MemorySanitizer: use-of-uninitialized-value third_party/qemu/net/tap-linux.c:183:9 in tap_probe_vnet_hdr_len
8
56
9
CC: qemu-stable@nongnu.org
57
Fixes: dc69004c7d8 ("net: move tap_probe_vnet_hdr() to tap-linux.c")
10
Reported-by: Daniel Shapira <daniel@twistlock.com>
58
Reviewed-by: Hao Wu <wuhaotsh@google.com>
11
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
59
Reviewed-by: Patrick Venture <venture@google.com>
60
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
61
Signed-off-by: Peter Foley <pefoley@google.com>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
62
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
---
63
---
14
hw/net/pcnet.c | 4 ++--
64
net/tap-linux.c | 1 +
15
1 file changed, 2 insertions(+), 2 deletions(-)
65
1 file changed, 1 insertion(+)
16
66
17
diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c
67
diff --git a/net/tap-linux.c b/net/tap-linux.c
18
index XXXXXXX..XXXXXXX 100644
68
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/net/pcnet.c
69
--- a/net/tap-linux.c
20
+++ b/hw/net/pcnet.c
70
+++ b/net/tap-linux.c
21
@@ -XXX,XX +XXX,XX @@ ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_)
71
@@ -XXX,XX +XXX,XX @@ void tap_set_sndbuf(int fd, const NetdevTapOptions *tap, Error **errp)
22
uint8_t buf1[60];
72
int tap_probe_vnet_hdr(int fd, Error **errp)
23
int remaining;
73
{
24
int crc_err = 0;
74
struct ifreq ifr;
25
- int size = size_;
75
+ memset(&ifr, 0, sizeof(ifr));
26
+ size_t size = size_;
76
27
77
if (ioctl(fd, TUNGETIFF, &ifr) != 0) {
28
if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size ||
78
/* TUNGETIFF is available since kernel v2.6.27 */
29
(CSR_LOOP(s) && !s->looptest)) {
30
return -1;
31
}
32
#ifdef PCNET_DEBUG
33
- printf("pcnet_receive size=%d\n", size);
34
+ printf("pcnet_receive size=%zu\n", size);
35
#endif
36
37
/* if too small buffer, then expand it */
38
--
79
--
39
2.5.0
80
2.7.4
40
81
41
82
diff view generated by jsdifflib
1
From: Zhang Chen <zhangckid@gmail.com>
1
From: Zhang Chen <chen.zhang@intel.com>
2
2
3
It's a good idea to use notifier to notify COLO frame of
3
COLO-compare use the glib function g_queue_find_custom to dump
4
inconsistent packets comparing.
4
another VM's networking packet to compare. But this function always
5
start find from the queue->head(here is the newest packet), It will
6
reduce the success rate of comparison. So this patch reversed
7
the order of the queues for performance.
5
8
6
Signed-off-by: Zhang Chen <zhangckid@gmail.com>
7
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
9
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
8
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
10
Reported-by: leirao <lei.rao@intel.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
12
---
11
net/colo-compare.c | 37 ++++++++++++++++++++++++++-----------
13
net/colo-compare.c | 26 +++++++++++++-------------
12
net/colo-compare.h | 2 ++
14
1 file changed, 13 insertions(+), 13 deletions(-)
13
2 files changed, 28 insertions(+), 11 deletions(-)
14
15
15
diff --git a/net/colo-compare.c b/net/colo-compare.c
16
diff --git a/net/colo-compare.c b/net/colo-compare.c
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/net/colo-compare.c
18
--- a/net/colo-compare.c
18
+++ b/net/colo-compare.c
19
+++ b/net/colo-compare.c
19
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ static void colo_compare_inconsistency_notify(CompareState *s)
20
#include "sysemu/iothread.h"
21
/* Use restricted to colo_insert_packet() */
21
#include "net/colo-compare.h"
22
static gint seq_sorter(Packet *a, Packet *b, gpointer data)
22
#include "migration/colo.h"
23
{
23
+#include "migration/migration.h"
24
- return a->tcp_seq - b->tcp_seq;
24
25
+ return b->tcp_seq - a->tcp_seq;
25
#define TYPE_COLO_COMPARE "colo-compare"
26
#define COLO_COMPARE(obj) \
27
@@ -XXX,XX +XXX,XX @@
28
static QTAILQ_HEAD(, CompareState) net_compares =
29
QTAILQ_HEAD_INITIALIZER(net_compares);
30
31
+static NotifierList colo_compare_notifiers =
32
+ NOTIFIER_LIST_INITIALIZER(colo_compare_notifiers);
33
+
34
#define COMPARE_READ_LEN_MAX NET_BUFSIZE
35
#define MAX_QUEUE_SIZE 1024
36
37
@@ -XXX,XX +XXX,XX @@ static bool colo_mark_tcp_pkt(Packet *ppkt, Packet *spkt,
38
return false;
39
}
26
}
40
27
41
+static void colo_compare_inconsistency_notify(void)
28
static void fill_pkt_tcp_info(void *data, uint32_t *max_ack)
42
+{
29
@@ -XXX,XX +XXX,XX @@ pri:
43
+ notifier_list_notify(&colo_compare_notifiers,
30
if (g_queue_is_empty(&conn->primary_list)) {
44
+ migrate_get_current());
31
return;
45
+}
32
}
46
+
33
- ppkt = g_queue_pop_head(&conn->primary_list);
47
static void colo_compare_tcp(CompareState *s, Connection *conn)
34
+ ppkt = g_queue_pop_tail(&conn->primary_list);
48
{
35
sec:
49
Packet *ppkt = NULL, *spkt = NULL;
36
if (g_queue_is_empty(&conn->secondary_list)) {
37
- g_queue_push_head(&conn->primary_list, ppkt);
38
+ g_queue_push_tail(&conn->primary_list, ppkt);
39
return;
40
}
41
- spkt = g_queue_pop_head(&conn->secondary_list);
42
+ spkt = g_queue_pop_tail(&conn->secondary_list);
43
44
if (ppkt->tcp_seq == ppkt->seq_end) {
45
colo_release_primary_pkt(s, ppkt);
50
@@ -XXX,XX +XXX,XX @@ sec:
46
@@ -XXX,XX +XXX,XX @@ sec:
51
qemu_hexdump((char *)spkt->data, stderr,
47
}
52
"colo-compare spkt", spkt->size);
48
}
53
49
if (!ppkt) {
54
- /*
50
- g_queue_push_head(&conn->secondary_list, spkt);
55
- * colo_compare_inconsistent_notify();
51
+ g_queue_push_tail(&conn->secondary_list, spkt);
56
- * TODO: notice to checkpoint();
52
goto pri;
57
- */
53
}
58
+ colo_compare_inconsistency_notify();
54
}
55
@@ -XXX,XX +XXX,XX @@ sec:
56
if (mark == COLO_COMPARE_FREE_PRIMARY) {
57
conn->compare_seq = ppkt->seq_end;
58
colo_release_primary_pkt(s, ppkt);
59
- g_queue_push_head(&conn->secondary_list, spkt);
60
+ g_queue_push_tail(&conn->secondary_list, spkt);
61
goto pri;
62
} else if (mark == COLO_COMPARE_FREE_SECONDARY) {
63
conn->compare_seq = spkt->seq_end;
64
@@ -XXX,XX +XXX,XX @@ sec:
65
goto pri;
66
}
67
} else {
68
- g_queue_push_head(&conn->primary_list, ppkt);
69
- g_queue_push_head(&conn->secondary_list, spkt);
70
+ g_queue_push_tail(&conn->primary_list, ppkt);
71
+ g_queue_push_tail(&conn->secondary_list, spkt);
72
73
#ifdef DEBUG_COLO_PACKETS
74
qemu_hexdump(stderr, "colo-compare ppkt", ppkt->data, ppkt->size);
75
@@ -XXX,XX +XXX,XX @@ static void colo_compare_packet(CompareState *s, Connection *conn,
76
77
while (!g_queue_is_empty(&conn->primary_list) &&
78
!g_queue_is_empty(&conn->secondary_list)) {
79
- pkt = g_queue_pop_head(&conn->primary_list);
80
+ pkt = g_queue_pop_tail(&conn->primary_list);
81
result = g_queue_find_custom(&conn->secondary_list,
82
pkt, (GCompareFunc)HandlePacket);
83
84
@@ -XXX,XX +XXX,XX @@ static void colo_compare_packet(CompareState *s, Connection *conn,
85
* timeout, it will trigger a checkpoint request.
86
*/
87
trace_colo_compare_main("packet different");
88
- g_queue_push_head(&conn->primary_list, pkt);
89
+ g_queue_push_tail(&conn->primary_list, pkt);
90
91
colo_compare_inconsistency_notify(s);
92
break;
93
@@ -XXX,XX +XXX,XX @@ static int compare_chr_send(CompareState *s,
94
entry->buf = g_malloc(size);
95
memcpy(entry->buf, buf, size);
96
}
97
- g_queue_push_head(&sendco->send_list, entry);
98
+ g_queue_push_tail(&sendco->send_list, entry);
99
100
if (sendco->done) {
101
sendco->co = qemu_coroutine_create(_compare_chr_send, sendco);
102
@@ -XXX,XX +XXX,XX @@ static void colo_flush_packets(void *opaque, void *user_data)
103
Packet *pkt = NULL;
104
105
while (!g_queue_is_empty(&conn->primary_list)) {
106
- pkt = g_queue_pop_head(&conn->primary_list);
107
+ pkt = g_queue_pop_tail(&conn->primary_list);
108
compare_chr_send(s,
109
pkt->data,
110
pkt->size,
111
@@ -XXX,XX +XXX,XX @@ static void colo_flush_packets(void *opaque, void *user_data)
112
packet_destroy_partial(pkt, NULL);
113
}
114
while (!g_queue_is_empty(&conn->secondary_list)) {
115
- pkt = g_queue_pop_head(&conn->secondary_list);
116
+ pkt = g_queue_pop_tail(&conn->secondary_list);
117
packet_destroy(pkt, NULL);
59
}
118
}
60
}
119
}
61
62
@@ -XXX,XX +XXX,XX @@ static int colo_old_packet_check_one(Packet *pkt, int64_t *check_time)
63
}
64
}
65
66
+void colo_compare_register_notifier(Notifier *notify)
67
+{
68
+ notifier_list_add(&colo_compare_notifiers, notify);
69
+}
70
+
71
+void colo_compare_unregister_notifier(Notifier *notify)
72
+{
73
+ notifier_remove(notify);
74
+}
75
+
76
static int colo_old_packet_check_one_conn(Connection *conn,
77
- void *user_data)
78
+ void *user_data)
79
{
80
GList *result = NULL;
81
int64_t check_time = REGULAR_PACKET_CHECK_MS;
82
@@ -XXX,XX +XXX,XX @@ static int colo_old_packet_check_one_conn(Connection *conn,
83
84
if (result) {
85
/* Do checkpoint will flush old packet */
86
- /*
87
- * TODO: Notify colo frame to do checkpoint.
88
- * colo_compare_inconsistent_notify();
89
- */
90
+ colo_compare_inconsistency_notify();
91
return 0;
92
}
93
94
@@ -XXX,XX +XXX,XX @@ static void colo_compare_packet(CompareState *s, Connection *conn,
95
/*
96
* If one packet arrive late, the secondary_list or
97
* primary_list will be empty, so we can't compare it
98
- * until next comparison.
99
+ * until next comparison. If the packets in the list are
100
+ * timeout, it will trigger a checkpoint request.
101
*/
102
trace_colo_compare_main("packet different");
103
g_queue_push_head(&conn->primary_list, pkt);
104
- /* TODO: colo_notify_checkpoint();*/
105
+ colo_compare_inconsistency_notify();
106
break;
107
}
108
}
109
diff --git a/net/colo-compare.h b/net/colo-compare.h
110
index XXXXXXX..XXXXXXX 100644
111
--- a/net/colo-compare.h
112
+++ b/net/colo-compare.h
113
@@ -XXX,XX +XXX,XX @@
114
#define QEMU_COLO_COMPARE_H
115
116
void colo_notify_compares_event(void *opaque, int event, Error **errp);
117
+void colo_compare_register_notifier(Notifier *notify);
118
+void colo_compare_unregister_notifier(Notifier *notify);
119
120
#endif /* QEMU_COLO_COMPARE_H */
121
--
120
--
122
2.5.0
121
2.7.4
123
122
124
123
diff view generated by jsdifflib
1
From: Zhang Chen <zhangckid@gmail.com>
1
From: Zhang Chen <chen.zhang@intel.com>
2
2
3
After one round of checkpoint, the states between PVM and SVM
3
Make the comments consistent with the REGULAR_PACKET_CHECK_MS.
4
become consistent, so it is unnecessary to adjust the sequence
5
of net packets for old connections, besides, while failover
6
happens, filter-rewriter will into failover mode that needn't
7
handle the new TCP connection.
8
4
9
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
10
Signed-off-by: Zhang Chen <zhangckid@gmail.com>
11
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
5
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
---
7
---
14
net/colo-compare.c | 12 +++++------
8
net/colo-compare.c | 2 +-
15
net/colo.c | 8 ++++++++
9
1 file changed, 1 insertion(+), 1 deletion(-)
16
net/colo.h | 2 ++
17
net/filter-rewriter.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++
18
4 files changed, 73 insertions(+), 6 deletions(-)
19
10
20
diff --git a/net/colo-compare.c b/net/colo-compare.c
11
diff --git a/net/colo-compare.c b/net/colo-compare.c
21
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
22
--- a/net/colo-compare.c
13
--- a/net/colo-compare.c
23
+++ b/net/colo-compare.c
14
+++ b/net/colo-compare.c
24
@@ -XXX,XX +XXX,XX @@ enum {
15
@@ -XXX,XX +XXX,XX @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
25
SECONDARY_IN,
26
};
27
28
+static void colo_compare_inconsistency_notify(void)
29
+{
30
+ notifier_list_notify(&colo_compare_notifiers,
31
+ migrate_get_current());
32
+}
33
+
34
static int compare_chr_send(CompareState *s,
35
const uint8_t *buf,
36
uint32_t size,
37
@@ -XXX,XX +XXX,XX @@ static bool colo_mark_tcp_pkt(Packet *ppkt, Packet *spkt,
38
return false;
39
}
40
41
-static void colo_compare_inconsistency_notify(void)
42
-{
43
- notifier_list_notify(&colo_compare_notifiers,
44
- migrate_get_current());
45
-}
46
-
47
static void colo_compare_tcp(CompareState *s, Connection *conn)
48
{
49
Packet *ppkt = NULL, *spkt = NULL;
50
diff --git a/net/colo.c b/net/colo.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/net/colo.c
53
+++ b/net/colo.c
54
@@ -XXX,XX +XXX,XX @@ Connection *connection_get(GHashTable *connection_track_table,
55
56
return conn;
57
}
58
+
59
+bool connection_has_tracked(GHashTable *connection_track_table,
60
+ ConnectionKey *key)
61
+{
62
+ Connection *conn = g_hash_table_lookup(connection_track_table, key);
63
+
64
+ return conn ? true : false;
65
+}
66
diff --git a/net/colo.h b/net/colo.h
67
index XXXXXXX..XXXXXXX 100644
68
--- a/net/colo.h
69
+++ b/net/colo.h
70
@@ -XXX,XX +XXX,XX @@ void connection_destroy(void *opaque);
71
Connection *connection_get(GHashTable *connection_track_table,
72
ConnectionKey *key,
73
GQueue *conn_list);
74
+bool connection_has_tracked(GHashTable *connection_track_table,
75
+ ConnectionKey *key);
76
void connection_hashtable_reset(GHashTable *connection_track_table);
77
Packet *packet_new(const void *data, int size, int vnet_hdr_len);
78
void packet_destroy(void *opaque, void *user_data);
79
diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/net/filter-rewriter.c
82
+++ b/net/filter-rewriter.c
83
@@ -XXX,XX +XXX,XX @@
84
#include "qemu/main-loop.h"
85
#include "qemu/iov.h"
86
#include "net/checksum.h"
87
+#include "net/colo.h"
88
+#include "migration/colo.h"
89
90
#define FILTER_COLO_REWRITER(obj) \
91
OBJECT_CHECK(RewriterState, (obj), TYPE_FILTER_REWRITER)
92
93
#define TYPE_FILTER_REWRITER "filter-rewriter"
94
+#define FAILOVER_MODE_ON true
95
+#define FAILOVER_MODE_OFF false
96
97
typedef struct RewriterState {
98
NetFilterState parent_obj;
99
@@ -XXX,XX +XXX,XX @@ typedef struct RewriterState {
100
/* hashtable to save connection */
101
GHashTable *connection_track_table;
102
bool vnet_hdr;
103
+ bool failover_mode;
104
} RewriterState;
105
106
+static void filter_rewriter_failover_mode(RewriterState *s)
107
+{
108
+ s->failover_mode = FAILOVER_MODE_ON;
109
+}
110
+
111
static void filter_rewriter_flush(NetFilterState *nf)
112
{
113
RewriterState *s = FILTER_COLO_REWRITER(nf);
114
@@ -XXX,XX +XXX,XX @@ static ssize_t colo_rewriter_receive_iov(NetFilterState *nf,
115
*/
116
reverse_connection_key(&key);
117
}
118
+
119
+ /* After failover we needn't change new TCP packet */
120
+ if (s->failover_mode &&
121
+ !connection_has_tracked(s->connection_track_table, &key)) {
122
+ goto out;
123
+ }
124
+
125
conn = connection_get(s->connection_track_table,
126
&key,
127
NULL);
128
@@ -XXX,XX +XXX,XX @@ static ssize_t colo_rewriter_receive_iov(NetFilterState *nf,
129
}
130
}
16
}
131
17
132
+out:
18
if (!s->expired_scan_cycle) {
133
packet_destroy(pkt, NULL);
19
- /* Set default value to 3000 MS */
134
pkt = NULL;
20
+ /* Set default value to 1000 MS */
135
return 0;
21
s->expired_scan_cycle = REGULAR_PACKET_CHECK_MS;
136
}
22
}
137
23
138
+static void reset_seq_offset(gpointer key, gpointer value, gpointer user_data)
139
+{
140
+ Connection *conn = (Connection *)value;
141
+
142
+ conn->offset = 0;
143
+}
144
+
145
+static gboolean offset_is_nonzero(gpointer key,
146
+ gpointer value,
147
+ gpointer user_data)
148
+{
149
+ Connection *conn = (Connection *)value;
150
+
151
+ return conn->offset ? true : false;
152
+}
153
+
154
+static void colo_rewriter_handle_event(NetFilterState *nf, int event,
155
+ Error **errp)
156
+{
157
+ RewriterState *rs = FILTER_COLO_REWRITER(nf);
158
+
159
+ switch (event) {
160
+ case COLO_EVENT_CHECKPOINT:
161
+ g_hash_table_foreach(rs->connection_track_table,
162
+ reset_seq_offset, NULL);
163
+ break;
164
+ case COLO_EVENT_FAILOVER:
165
+ if (!g_hash_table_find(rs->connection_track_table,
166
+ offset_is_nonzero, NULL)) {
167
+ filter_rewriter_failover_mode(rs);
168
+ }
169
+ break;
170
+ default:
171
+ break;
172
+ }
173
+}
174
+
175
static void colo_rewriter_cleanup(NetFilterState *nf)
176
{
177
RewriterState *s = FILTER_COLO_REWRITER(nf);
178
@@ -XXX,XX +XXX,XX @@ static void filter_rewriter_init(Object *obj)
179
RewriterState *s = FILTER_COLO_REWRITER(obj);
180
181
s->vnet_hdr = false;
182
+ s->failover_mode = FAILOVER_MODE_OFF;
183
object_property_add_bool(obj, "vnet_hdr_support",
184
filter_rewriter_get_vnet_hdr,
185
filter_rewriter_set_vnet_hdr, NULL);
186
@@ -XXX,XX +XXX,XX @@ static void colo_rewriter_class_init(ObjectClass *oc, void *data)
187
nfc->setup = colo_rewriter_setup;
188
nfc->cleanup = colo_rewriter_cleanup;
189
nfc->receive_iov = colo_rewriter_receive_iov;
190
+ nfc->handle_event = colo_rewriter_handle_event;
191
}
192
193
static const TypeInfo colo_rewriter_info = {
194
--
24
--
195
2.5.0
25
2.7.4
196
26
197
27
diff view generated by jsdifflib
1
From: Zhang Chen <zhangckid@gmail.com>
1
From: Rao Lei <lei.rao@intel.com>
2
2
3
For COLO FT, both the PVM and SVM run at the same time,
3
This patch is to improve the logic of QEMU main thread sleep code in
4
only sync the state while it needs.
4
qemu_chr_write_buffer() where it can be blocked and can't run other
5
coroutines during COLO IO stress test.
5
6
6
So here, let SVM runs while not doing checkpoint, change
7
Our approach is to put filter_send() in a coroutine. In this way,
7
DEFAULT_MIGRATE_X_CHECKPOINT_DELAY to 200*100.
8
filter_send() will call qemu_coroutine_yield() in qemu_co_sleep_ns(),
9
so that it can be scheduled out and QEMU main thread has opportunity to
10
run other tasks.
8
11
9
Besides, we forgot to release colo_checkpoint_semd and
12
Signed-off-by: Lei Rao <lei.rao@intel.com>
10
colo_delay_timer, fix them here.
11
12
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
13
Signed-off-by: Zhang Chen <zhangckid@gmail.com>
14
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
13
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
15
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
14
Reviewed-by: Li Zhijian <lizhijian@fujitsu.com>
15
Reviewed-by: Zhang Chen <chen.zhang@intel.com>
16
Signed-off-by: Jason Wang <jasowang@redhat.com>
16
Signed-off-by: Jason Wang <jasowang@redhat.com>
17
---
17
---
18
migration/colo.c | 42 ++++++++++++++++++++++++++++++++++++++++--
18
net/filter-mirror.c | 66 ++++++++++++++++++++++++++++++++++++++++++-----------
19
migration/migration.c | 6 ++----
19
1 file changed, 53 insertions(+), 13 deletions(-)
20
2 files changed, 42 insertions(+), 6 deletions(-)
21
20
22
diff --git a/migration/colo.c b/migration/colo.c
21
diff --git a/net/filter-mirror.c b/net/filter-mirror.c
23
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
24
--- a/migration/colo.c
23
--- a/net/filter-mirror.c
25
+++ b/migration/colo.c
24
+++ b/net/filter-mirror.c
26
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@
27
#include "qemu/error-report.h"
26
#include "chardev/char-fe.h"
28
#include "migration/failover.h"
27
#include "qemu/iov.h"
29
#include "replication.h"
28
#include "qemu/sockets.h"
30
+#include "net/colo-compare.h"
29
+#include "block/aio-wait.h"
31
+#include "net/colo.h"
30
32
31
#define TYPE_FILTER_MIRROR "filter-mirror"
33
static bool vmstate_loading;
32
typedef struct MirrorState MirrorState;
34
+static Notifier packets_compare_notifier;
33
@@ -XXX,XX +XXX,XX @@ struct MirrorState {
35
34
bool vnet_hdr;
36
#define COLO_BUFFER_BASE_SIZE (4 * 1024 * 1024)
35
};
37
36
38
@@ -XXX,XX +XXX,XX @@ static int colo_do_checkpoint_transaction(MigrationState *s,
37
-static int filter_send(MirrorState *s,
39
goto out;
38
- const struct iovec *iov,
39
- int iovcnt)
40
+typedef struct FilterSendCo {
41
+ MirrorState *s;
42
+ char *buf;
43
+ ssize_t size;
44
+ bool done;
45
+ int ret;
46
+} FilterSendCo;
47
+
48
+static int _filter_send(MirrorState *s,
49
+ char *buf,
50
+ ssize_t size)
51
{
52
NetFilterState *nf = NETFILTER(s);
53
int ret = 0;
54
- ssize_t size = 0;
55
uint32_t len = 0;
56
- char *buf;
57
-
58
- size = iov_size(iov, iovcnt);
59
- if (!size) {
60
- return 0;
61
- }
62
63
len = htonl(size);
64
ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len));
65
@@ -XXX,XX +XXX,XX @@ static int filter_send(MirrorState *s,
66
}
40
}
67
}
41
68
42
+ colo_notify_compares_event(NULL, COLO_EVENT_CHECKPOINT, &local_err);
69
- buf = g_malloc(size);
43
+ if (local_err) {
70
- iov_to_buf(iov, iovcnt, 0, buf, size);
44
+ goto out;
71
ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)buf, size);
72
- g_free(buf);
73
if (ret != size) {
74
goto err;
75
}
76
@@ -XXX,XX +XXX,XX @@ err:
77
return ret < 0 ? ret : -EIO;
78
}
79
80
+static void coroutine_fn filter_send_co(void *opaque)
81
+{
82
+ FilterSendCo *data = opaque;
83
+
84
+ data->ret = _filter_send(data->s, data->buf, data->size);
85
+ data->done = true;
86
+ g_free(data->buf);
87
+ aio_wait_kick();
88
+}
89
+
90
+static int filter_send(MirrorState *s,
91
+ const struct iovec *iov,
92
+ int iovcnt)
93
+{
94
+ ssize_t size = iov_size(iov, iovcnt);
95
+ char *buf = NULL;
96
+
97
+ if (!size) {
98
+ return 0;
45
+ }
99
+ }
46
+
100
+
47
/* Disable block migration */
101
+ buf = g_malloc(size);
48
migrate_set_block_enabled(false, &local_err);
102
+ iov_to_buf(iov, iovcnt, 0, buf, size);
49
qemu_savevm_state_header(fb);
103
+
50
@@ -XXX,XX +XXX,XX @@ out:
104
+ FilterSendCo data = {
51
return ret;
105
+ .s = s,
52
}
106
+ .size = size,
53
107
+ .buf = buf,
54
+static void colo_compare_notify_checkpoint(Notifier *notifier, void *data)
108
+ .ret = 0,
55
+{
109
+ };
56
+ colo_checkpoint_notify(data);
110
+
111
+ Coroutine *co = qemu_coroutine_create(filter_send_co, &data);
112
+ qemu_coroutine_enter(co);
113
+
114
+ while (!data.done) {
115
+ aio_poll(qemu_get_aio_context(), true);
116
+ }
117
+
118
+ return data.ret;
57
+}
119
+}
58
+
120
+
59
static void colo_process_checkpoint(MigrationState *s)
121
static void redirector_to_filter(NetFilterState *nf,
60
{
122
const uint8_t *buf,
61
QIOChannelBuffer *bioc;
123
int len)
62
@@ -XXX,XX +XXX,XX @@ static void colo_process_checkpoint(MigrationState *s)
63
goto out;
64
}
65
66
+ packets_compare_notifier.notify = colo_compare_notify_checkpoint;
67
+ colo_compare_register_notifier(&packets_compare_notifier);
68
+
69
/*
70
* Wait for Secondary finish loading VM states and enter COLO
71
* restore.
72
@@ -XXX,XX +XXX,XX @@ out:
73
qemu_fclose(fb);
74
}
75
76
- timer_del(s->colo_delay_timer);
77
-
78
/* Hope this not to be too long to wait here */
79
qemu_sem_wait(&s->colo_exit_sem);
80
qemu_sem_destroy(&s->colo_exit_sem);
81
+
82
+ /*
83
+ * It is safe to unregister notifier after failover finished.
84
+ * Besides, colo_delay_timer and colo_checkpoint_sem can't be
85
+ * released befor unregister notifier, or there will be use-after-free
86
+ * error.
87
+ */
88
+ colo_compare_unregister_notifier(&packets_compare_notifier);
89
+ timer_del(s->colo_delay_timer);
90
+ timer_free(s->colo_delay_timer);
91
+ qemu_sem_destroy(&s->colo_checkpoint_sem);
92
+
93
/*
94
* Must be called after failover BH is completed,
95
* Or the failover BH may shutdown the wrong fd that
96
@@ -XXX,XX +XXX,XX @@ void *colo_process_incoming_thread(void *opaque)
97
fb = qemu_fopen_channel_input(QIO_CHANNEL(bioc));
98
object_unref(OBJECT(bioc));
99
100
+ qemu_mutex_lock_iothread();
101
+ vm_start();
102
+ trace_colo_vm_state_change("stop", "run");
103
+ qemu_mutex_unlock_iothread();
104
+
105
colo_send_message(mis->to_src_file, COLO_MESSAGE_CHECKPOINT_READY,
106
&local_err);
107
if (local_err) {
108
@@ -XXX,XX +XXX,XX @@ void *colo_process_incoming_thread(void *opaque)
109
goto out;
110
}
111
112
+ qemu_mutex_lock_iothread();
113
+ vm_stop_force_state(RUN_STATE_COLO);
114
+ trace_colo_vm_state_change("run", "stop");
115
+ qemu_mutex_unlock_iothread();
116
+
117
/* FIXME: This is unnecessary for periodic checkpoint mode */
118
colo_send_message(mis->to_src_file, COLO_MESSAGE_CHECKPOINT_REPLY,
119
&local_err);
120
@@ -XXX,XX +XXX,XX @@ void *colo_process_incoming_thread(void *opaque)
121
}
122
123
vmstate_loading = false;
124
+ vm_start();
125
+ trace_colo_vm_state_change("stop", "run");
126
qemu_mutex_unlock_iothread();
127
128
if (failover_get_state() == FAILOVER_STATUS_RELAUNCH) {
129
diff --git a/migration/migration.c b/migration/migration.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/migration/migration.c
132
+++ b/migration/migration.c
133
@@ -XXX,XX +XXX,XX @@
134
/* Migration XBZRLE default cache size */
135
#define DEFAULT_MIGRATE_XBZRLE_CACHE_SIZE (64 * 1024 * 1024)
136
137
-/* The delay time (in ms) between two COLO checkpoints
138
- * Note: Please change this default value to 10000 when we support hybrid mode.
139
- */
140
-#define DEFAULT_MIGRATE_X_CHECKPOINT_DELAY 200
141
+/* The delay time (in ms) between two COLO checkpoints */
142
+#define DEFAULT_MIGRATE_X_CHECKPOINT_DELAY (200 * 100)
143
#define DEFAULT_MIGRATE_MULTIFD_CHANNELS 2
144
#define DEFAULT_MIGRATE_MULTIFD_PAGE_COUNT 16
145
146
--
124
--
147
2.5.0
125
2.7.4
148
126
149
127
diff view generated by jsdifflib
1
In rtl8139_do_receive(), we try to assign size_ to size which converts
1
From: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
2
from size_t to integer. This will cause troubles when size_ is greater
3
INT_MAX, this will lead a negative value in size and it can then pass
4
the check of size < MIN_BUF_SIZE which may lead out of bound access of
5
for both buf and buf1.
6
2
7
Fixing by converting the type of size to size_t.
3
vmnet.framework dependency is added with 'vmnet' option
4
to enable or disable it. Default value is 'auto'.
8
5
9
CC: qemu-stable@nongnu.org
6
vmnet features to be used are available since macOS 11.0,
10
Reported-by: Daniel Shapira <daniel@twistlock.com>
7
corresponding probe is created into meson.build.
11
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
8
9
Signed-off-by: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
---
11
---
14
hw/net/rtl8139.c | 8 ++++----
12
meson.build | 16 +++++++++++++++-
15
1 file changed, 4 insertions(+), 4 deletions(-)
13
meson_options.txt | 2 ++
14
scripts/meson-buildoptions.sh | 3 +++
15
3 files changed, 20 insertions(+), 1 deletion(-)
16
16
17
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
17
diff --git a/meson.build b/meson.build
18
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/net/rtl8139.c
19
--- a/meson.build
20
+++ b/hw/net/rtl8139.c
20
+++ b/meson.build
21
@@ -XXX,XX +XXX,XX @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t
21
@@ -XXX,XX +XXX,XX @@ if cocoa.found() and get_option('gtk').enabled()
22
RTL8139State *s = qemu_get_nic_opaque(nc);
22
error('Cocoa and GTK+ cannot be enabled at the same time')
23
PCIDevice *d = PCI_DEVICE(s);
23
endif
24
/* size is the length of the buffer passed to the driver */
24
25
- int size = size_;
25
+vmnet = dependency('appleframeworks', modules: 'vmnet', required: get_option('vmnet'))
26
+ size_t size = size_;
26
+if vmnet.found() and not cc.has_header_symbol('vmnet/vmnet.h',
27
const uint8_t *dot1q_buf = NULL;
27
+ 'VMNET_BRIDGED_MODE',
28
28
+ dependencies: vmnet)
29
uint32_t packet_header = 0;
29
+ vmnet = not_found
30
@@ -XXX,XX +XXX,XX @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t
30
+ if get_option('vmnet').enabled()
31
static const uint8_t broadcast_macaddr[6] =
31
+ error('vmnet.framework API is outdated')
32
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
32
+ else
33
33
+ warning('vmnet.framework API is outdated, disabling')
34
- DPRINTF(">>> received len=%d\n", size);
34
+ endif
35
+ DPRINTF(">>> received len=%zu\n", size);
35
+endif
36
36
+
37
/* test if board clock is stopped */
37
seccomp = not_found
38
if (!s->clock_enabled)
38
if not get_option('seccomp').auto() or have_system or have_tools
39
@@ -XXX,XX +XXX,XX @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t
39
seccomp = dependency('libseccomp', version: '>=2.3.0',
40
40
@@ -XXX,XX +XXX,XX @@ config_host_data.set('CONFIG_SECCOMP', seccomp.found())
41
if (size+4 > rx_space)
41
config_host_data.set('CONFIG_SNAPPY', snappy.found())
42
{
42
config_host_data.set('CONFIG_USB_LIBUSB', libusb.found())
43
- DPRINTF("C+ Rx mode : descriptor %d size %d received %d + 4\n",
43
config_host_data.set('CONFIG_VDE', vde.found())
44
+ DPRINTF("C+ Rx mode : descriptor %d size %d received %zu + 4\n",
44
+config_host_data.set('CONFIG_VMNET', vmnet.found())
45
descriptor, rx_space, size);
45
config_host_data.set('CONFIG_VHOST_USER_BLK_SERVER', have_vhost_user_blk_server)
46
46
config_host_data.set('CONFIG_VNC', vnc.found())
47
s->IntrStatus |= RxOverflow;
47
config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
48
@@ -XXX,XX +XXX,XX @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t
48
@@ -XXX,XX +XXX,XX @@ summary(summary_info, bool_yn: true, section: 'Crypto')
49
if (avail != 0 && RX_ALIGN(size + 8) >= avail)
49
# Libraries
50
{
50
summary_info = {}
51
DPRINTF("rx overflow: rx buffer length %d head 0x%04x "
51
if targetos == 'darwin'
52
- "read 0x%04x === available 0x%04x need 0x%04x\n",
52
- summary_info += {'Cocoa support': cocoa}
53
+ "read 0x%04x === available 0x%04x need 0x%04zx\n",
53
+ summary_info += {'Cocoa support': cocoa}
54
s->RxBufferSize, s->RxBufAddr, s->RxBufPtr, avail, size + 8);
54
+ summary_info += {'vmnet.framework support': vmnet}
55
55
endif
56
s->IntrStatus |= RxOverflow;
56
summary_info += {'SDL support': sdl}
57
summary_info += {'SDL image support': sdl_image}
58
diff --git a/meson_options.txt b/meson_options.txt
59
index XXXXXXX..XXXXXXX 100644
60
--- a/meson_options.txt
61
+++ b/meson_options.txt
62
@@ -XXX,XX +XXX,XX @@ option('netmap', type : 'feature', value : 'auto',
63
description: 'netmap network backend support')
64
option('vde', type : 'feature', value : 'auto',
65
description: 'vde network backend support')
66
+option('vmnet', type : 'feature', value : 'auto',
67
+ description: 'vmnet.framework network backend support')
68
option('virglrenderer', type : 'feature', value : 'auto',
69
description: 'virgl rendering support')
70
option('vnc', type : 'feature', value : 'auto',
71
diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh
72
index XXXXXXX..XXXXXXX 100644
73
--- a/scripts/meson-buildoptions.sh
74
+++ b/scripts/meson-buildoptions.sh
75
@@ -XXX,XX +XXX,XX @@ meson_options_help() {
76
printf "%s\n" ' u2f U2F emulation support'
77
printf "%s\n" ' usb-redir libusbredir support'
78
printf "%s\n" ' vde vde network backend support'
79
+ printf "%s\n" ' vmnet vmnet.framework network backend support'
80
printf "%s\n" ' vhost-user-blk-server'
81
printf "%s\n" ' build vhost-user-blk server'
82
printf "%s\n" ' virglrenderer virgl rendering support'
83
@@ -XXX,XX +XXX,XX @@ _meson_option_parse() {
84
--disable-usb-redir) printf "%s" -Dusb_redir=disabled ;;
85
--enable-vde) printf "%s" -Dvde=enabled ;;
86
--disable-vde) printf "%s" -Dvde=disabled ;;
87
+ --enable-vmnet) printf "%s" -Dvmnet=enabled ;;
88
+ --disable-vmnet) printf "%s" -Dvmnet=disabled ;;
89
--enable-vhost-user-blk-server) printf "%s" -Dvhost_user_blk_server=enabled ;;
90
--disable-vhost-user-blk-server) printf "%s" -Dvhost_user_blk_server=disabled ;;
91
--enable-virglrenderer) printf "%s" -Dvirglrenderer=enabled ;;
57
--
92
--
58
2.5.0
93
2.7.4
59
94
60
95
diff view generated by jsdifflib
1
From: Zhang Chen <zhangckid@gmail.com>
1
From: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
2
2
3
Filter needs to process the event of checkpoint/failover or
3
Create separate netdevs for each vmnet operating mode:
4
other event passed by COLO frame.
4
- vmnet-host
5
- vmnet-shared
6
- vmnet-bridged
5
7
6
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
8
Signed-off-by: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
7
Signed-off-by: Zhang Chen <zhangckid@gmail.com>
8
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
10
---
11
include/net/filter.h | 5 +++++
11
net/clients.h | 11 +++++
12
net/filter.c | 17 +++++++++++++++++
12
net/meson.build | 7 +++
13
net/net.c | 19 +++++++++++++++++++
13
net/net.c | 10 ++++
14
3 files changed, 41 insertions(+)
14
net/vmnet-bridged.m | 25 ++++++++++
15
net/vmnet-common.m | 19 ++++++++
16
net/vmnet-host.c | 24 ++++++++++
17
net/vmnet-shared.c | 25 ++++++++++
18
net/vmnet_int.h | 25 ++++++++++
19
qapi/net.json | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++-
20
9 files changed, 277 insertions(+), 2 deletions(-)
21
create mode 100644 net/vmnet-bridged.m
22
create mode 100644 net/vmnet-common.m
23
create mode 100644 net/vmnet-host.c
24
create mode 100644 net/vmnet-shared.c
25
create mode 100644 net/vmnet_int.h
15
26
16
diff --git a/include/net/filter.h b/include/net/filter.h
27
diff --git a/net/clients.h b/net/clients.h
17
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
18
--- a/include/net/filter.h
29
--- a/net/clients.h
19
+++ b/include/net/filter.h
30
+++ b/net/clients.h
20
@@ -XXX,XX +XXX,XX @@ typedef ssize_t (FilterReceiveIOV)(NetFilterState *nc,
31
@@ -XXX,XX +XXX,XX @@ int net_init_vhost_user(const Netdev *netdev, const char *name,
21
32
22
typedef void (FilterStatusChanged) (NetFilterState *nf, Error **errp);
33
int net_init_vhost_vdpa(const Netdev *netdev, const char *name,
23
34
NetClientState *peer, Error **errp);
24
+typedef void (FilterHandleEvent) (NetFilterState *nf, int event, Error **errp);
35
+#ifdef CONFIG_VMNET
25
+
36
+int net_init_vmnet_host(const Netdev *netdev, const char *name,
26
typedef struct NetFilterClass {
37
+ NetClientState *peer, Error **errp);
27
ObjectClass parent_class;
38
+
28
39
+int net_init_vmnet_shared(const Netdev *netdev, const char *name,
29
@@ -XXX,XX +XXX,XX @@ typedef struct NetFilterClass {
40
+ NetClientState *peer, Error **errp);
30
FilterSetup *setup;
41
+
31
FilterCleanup *cleanup;
42
+int net_init_vmnet_bridged(const Netdev *netdev, const char *name,
32
FilterStatusChanged *status_changed;
43
+ NetClientState *peer, Error **errp);
33
+ FilterHandleEvent *handle_event;
44
+#endif /* CONFIG_VMNET */
34
/* mandatory */
45
+
35
FilterReceiveIOV *receive_iov;
46
#endif /* QEMU_NET_CLIENTS_H */
36
} NetFilterClass;
47
diff --git a/net/meson.build b/net/meson.build
37
@@ -XXX,XX +XXX,XX @@ ssize_t qemu_netfilter_pass_to_next(NetClientState *sender,
38
int iovcnt,
39
void *opaque);
40
41
+void colo_notify_filters_event(int event, Error **errp);
42
+
43
#endif /* QEMU_NET_FILTER_H */
44
diff --git a/net/filter.c b/net/filter.c
45
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
46
--- a/net/filter.c
49
--- a/net/meson.build
47
+++ b/net/filter.c
50
+++ b/net/meson.build
48
@@ -XXX,XX +XXX,XX @@
51
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_POSIX', if_true: files(tap_posix))
49
#include "net/vhost_net.h"
52
softmmu_ss.add(when: 'CONFIG_WIN32', if_true: files('tap-win32.c'))
50
#include "qom/object_interfaces.h"
53
softmmu_ss.add(when: 'CONFIG_VHOST_NET_VDPA', if_true: files('vhost-vdpa.c'))
51
#include "qemu/iov.h"
54
52
+#include "net/colo.h"
55
+vmnet_files = files(
53
+#include "migration/colo.h"
56
+ 'vmnet-common.m',
54
57
+ 'vmnet-bridged.m',
55
static inline bool qemu_can_skip_netfilter(NetFilterState *nf)
58
+ 'vmnet-host.c',
56
{
59
+ 'vmnet-shared.c'
57
@@ -XXX,XX +XXX,XX @@ static void netfilter_finalize(Object *obj)
60
+)
58
g_free(nf->netdev_id);
61
+softmmu_ss.add(when: vmnet, if_true: vmnet_files)
59
}
62
subdir('can')
60
61
+static void default_handle_event(NetFilterState *nf, int event, Error **errp)
62
+{
63
+ switch (event) {
64
+ case COLO_EVENT_CHECKPOINT:
65
+ break;
66
+ case COLO_EVENT_FAILOVER:
67
+ object_property_set_str(OBJECT(nf), "off", "status", errp);
68
+ break;
69
+ default:
70
+ break;
71
+ }
72
+}
73
+
74
static void netfilter_class_init(ObjectClass *oc, void *data)
75
{
76
UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
77
+ NetFilterClass *nfc = NETFILTER_CLASS(oc);
78
79
ucc->complete = netfilter_complete;
80
+ nfc->handle_event = default_handle_event;
81
}
82
83
static const TypeInfo netfilter_info = {
84
diff --git a/net/net.c b/net/net.c
63
diff --git a/net/net.c b/net/net.c
85
index XXXXXXX..XXXXXXX 100644
64
index XXXXXXX..XXXXXXX 100644
86
--- a/net/net.c
65
--- a/net/net.c
87
+++ b/net/net.c
66
+++ b/net/net.c
88
@@ -XXX,XX +XXX,XX @@ void hmp_info_network(Monitor *mon, const QDict *qdict)
67
@@ -XXX,XX +XXX,XX @@ static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])(
89
}
68
#ifdef CONFIG_L2TPV3
90
}
69
[NET_CLIENT_DRIVER_L2TPV3] = net_init_l2tpv3,
91
70
#endif
92
+void colo_notify_filters_event(int event, Error **errp)
71
+#ifdef CONFIG_VMNET
72
+ [NET_CLIENT_DRIVER_VMNET_HOST] = net_init_vmnet_host,
73
+ [NET_CLIENT_DRIVER_VMNET_SHARED] = net_init_vmnet_shared,
74
+ [NET_CLIENT_DRIVER_VMNET_BRIDGED] = net_init_vmnet_bridged,
75
+#endif /* CONFIG_VMNET */
76
};
77
78
79
@@ -XXX,XX +XXX,XX @@ void show_netdevs(void)
80
#ifdef CONFIG_VHOST_VDPA
81
"vhost-vdpa",
82
#endif
83
+#ifdef CONFIG_VMNET
84
+ "vmnet-host",
85
+ "vmnet-shared",
86
+ "vmnet-bridged",
87
+#endif
88
};
89
90
qemu_printf("Available netdev backend types:\n");
91
diff --git a/net/vmnet-bridged.m b/net/vmnet-bridged.m
92
new file mode 100644
93
index XXXXXXX..XXXXXXX
94
--- /dev/null
95
+++ b/net/vmnet-bridged.m
96
@@ -XXX,XX +XXX,XX @@
97
+/*
98
+ * vmnet-bridged.m
99
+ *
100
+ * Copyright(c) 2021 Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
101
+ *
102
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
103
+ * See the COPYING file in the top-level directory.
104
+ *
105
+ */
106
+
107
+#include "qemu/osdep.h"
108
+#include "qapi/qapi-types-net.h"
109
+#include "vmnet_int.h"
110
+#include "clients.h"
111
+#include "qemu/error-report.h"
112
+#include "qapi/error.h"
113
+
114
+#include <vmnet/vmnet.h>
115
+
116
+int net_init_vmnet_bridged(const Netdev *netdev, const char *name,
117
+ NetClientState *peer, Error **errp)
93
+{
118
+{
94
+ NetClientState *nc;
119
+ error_setg(errp, "vmnet-bridged is not implemented yet");
95
+ NetFilterState *nf;
120
+ return -1;
96
+ NetFilterClass *nfc = NULL;
97
+ Error *local_err = NULL;
98
+
99
+ QTAILQ_FOREACH(nc, &net_clients, next) {
100
+ QTAILQ_FOREACH(nf, &nc->filters, next) {
101
+ nfc = NETFILTER_GET_CLASS(OBJECT(nf));
102
+ nfc->handle_event(nf, event, &local_err);
103
+ if (local_err) {
104
+ error_propagate(errp, local_err);
105
+ return;
106
+ }
107
+ }
108
+ }
109
+}
121
+}
110
+
122
diff --git a/net/vmnet-common.m b/net/vmnet-common.m
111
void qmp_set_link(const char *name, bool up, Error **errp)
123
new file mode 100644
112
{
124
index XXXXXXX..XXXXXXX
113
NetClientState *ncs[MAX_QUEUE_NUM];
125
--- /dev/null
126
+++ b/net/vmnet-common.m
127
@@ -XXX,XX +XXX,XX @@
128
+/*
129
+ * vmnet-common.m - network client wrapper for Apple vmnet.framework
130
+ *
131
+ * Copyright(c) 2021 Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
132
+ * Copyright(c) 2021 Phillip Tennen <phillip@axleos.com>
133
+ *
134
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
135
+ * See the COPYING file in the top-level directory.
136
+ *
137
+ */
138
+
139
+#include "qemu/osdep.h"
140
+#include "qapi/qapi-types-net.h"
141
+#include "vmnet_int.h"
142
+#include "clients.h"
143
+#include "qemu/error-report.h"
144
+#include "qapi/error.h"
145
+
146
+#include <vmnet/vmnet.h>
147
diff --git a/net/vmnet-host.c b/net/vmnet-host.c
148
new file mode 100644
149
index XXXXXXX..XXXXXXX
150
--- /dev/null
151
+++ b/net/vmnet-host.c
152
@@ -XXX,XX +XXX,XX @@
153
+/*
154
+ * vmnet-host.c
155
+ *
156
+ * Copyright(c) 2021 Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
157
+ *
158
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
159
+ * See the COPYING file in the top-level directory.
160
+ *
161
+ */
162
+
163
+#include "qemu/osdep.h"
164
+#include "qapi/qapi-types-net.h"
165
+#include "vmnet_int.h"
166
+#include "clients.h"
167
+#include "qemu/error-report.h"
168
+#include "qapi/error.h"
169
+
170
+#include <vmnet/vmnet.h>
171
+
172
+int net_init_vmnet_host(const Netdev *netdev, const char *name,
173
+ NetClientState *peer, Error **errp) {
174
+ error_setg(errp, "vmnet-host is not implemented yet");
175
+ return -1;
176
+}
177
diff --git a/net/vmnet-shared.c b/net/vmnet-shared.c
178
new file mode 100644
179
index XXXXXXX..XXXXXXX
180
--- /dev/null
181
+++ b/net/vmnet-shared.c
182
@@ -XXX,XX +XXX,XX @@
183
+/*
184
+ * vmnet-shared.c
185
+ *
186
+ * Copyright(c) 2021 Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
187
+ *
188
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
189
+ * See the COPYING file in the top-level directory.
190
+ *
191
+ */
192
+
193
+#include "qemu/osdep.h"
194
+#include "qapi/qapi-types-net.h"
195
+#include "vmnet_int.h"
196
+#include "clients.h"
197
+#include "qemu/error-report.h"
198
+#include "qapi/error.h"
199
+
200
+#include <vmnet/vmnet.h>
201
+
202
+int net_init_vmnet_shared(const Netdev *netdev, const char *name,
203
+ NetClientState *peer, Error **errp)
204
+{
205
+ error_setg(errp, "vmnet-shared is not implemented yet");
206
+ return -1;
207
+}
208
diff --git a/net/vmnet_int.h b/net/vmnet_int.h
209
new file mode 100644
210
index XXXXXXX..XXXXXXX
211
--- /dev/null
212
+++ b/net/vmnet_int.h
213
@@ -XXX,XX +XXX,XX @@
214
+/*
215
+ * vmnet_int.h
216
+ *
217
+ * Copyright(c) 2021 Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
218
+ *
219
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
220
+ * See the COPYING file in the top-level directory.
221
+ *
222
+ */
223
+#ifndef VMNET_INT_H
224
+#define VMNET_INT_H
225
+
226
+#include "qemu/osdep.h"
227
+#include "vmnet_int.h"
228
+#include "clients.h"
229
+
230
+#include <vmnet/vmnet.h>
231
+
232
+typedef struct VmnetCommonState {
233
+ NetClientState nc;
234
+
235
+} VmnetCommonState;
236
+
237
+
238
+#endif /* VMNET_INT_H */
239
diff --git a/qapi/net.json b/qapi/net.json
240
index XXXXXXX..XXXXXXX 100644
241
--- a/qapi/net.json
242
+++ b/qapi/net.json
243
@@ -XXX,XX +XXX,XX @@
244
'*queues': 'int' } }
245
246
##
247
+# @NetdevVmnetHostOptions:
248
+#
249
+# vmnet (host mode) network backend.
250
+#
251
+# Allows the vmnet interface to communicate with other vmnet
252
+# interfaces that are in host mode and also with the host.
253
+#
254
+# @start-address: The starting IPv4 address to use for the interface.
255
+# Must be in the private IP range (RFC 1918). Must be
256
+# specified along with @end-address and @subnet-mask.
257
+# This address is used as the gateway address. The
258
+# subsequent address up to and including end-address are
259
+# placed in the DHCP pool.
260
+#
261
+# @end-address: The DHCP IPv4 range end address to use for the
262
+# interface. Must be in the private IP range (RFC 1918).
263
+# Must be specified along with @start-address and
264
+# @subnet-mask.
265
+#
266
+# @subnet-mask: The IPv4 subnet mask to use on the interface. Must
267
+# be specified along with @start-address and @subnet-mask.
268
+#
269
+# @isolated: Enable isolation for this interface. Interface isolation
270
+# ensures that vmnet interface is not able to communicate
271
+# with any other vmnet interfaces. Only communication with
272
+# host is allowed. Available since macOS Big Sur 11.0.
273
+#
274
+# @net-uuid: The identifier (UUID) to uniquely identify the isolated
275
+# network vmnet interface should be added to. If
276
+# set, no DHCP service is provided for this interface and
277
+# network communication is allowed only with other interfaces
278
+# added to this network identified by the UUID. Available
279
+# since macOS Big Sur 11.0.
280
+#
281
+# Since: 7.0
282
+##
283
+{ 'struct': 'NetdevVmnetHostOptions',
284
+ 'data': {
285
+ '*start-address': 'str',
286
+ '*end-address': 'str',
287
+ '*subnet-mask': 'str',
288
+ '*isolated': 'bool',
289
+ '*net-uuid': 'str' },
290
+ 'if': 'CONFIG_VMNET' }
291
+
292
+##
293
+# @NetdevVmnetSharedOptions:
294
+#
295
+# vmnet (shared mode) network backend.
296
+#
297
+# Allows traffic originating from the vmnet interface to reach the
298
+# Internet through a network address translator (NAT).
299
+# The vmnet interface can communicate with the host and with
300
+# other shared mode interfaces on the same subnet. If no DHCP
301
+# settings, subnet mask and IPv6 prefix specified, the interface can
302
+# communicate with any of other interfaces in shared mode.
303
+#
304
+# @start-address: The starting IPv4 address to use for the interface.
305
+# Must be in the private IP range (RFC 1918). Must be
306
+# specified along with @end-address and @subnet-mask.
307
+# This address is used as the gateway address. The
308
+# subsequent address up to and including end-address are
309
+# placed in the DHCP pool.
310
+#
311
+# @end-address: The DHCP IPv4 range end address to use for the
312
+# interface. Must be in the private IP range (RFC 1918).
313
+# Must be specified along with @start-address and @subnet-mask.
314
+#
315
+# @subnet-mask: The IPv4 subnet mask to use on the interface. Must
316
+# be specified along with @start-address and @subnet-mask.
317
+#
318
+# @isolated: Enable isolation for this interface. Interface isolation
319
+# ensures that vmnet interface is not able to communicate
320
+# with any other vmnet interfaces. Only communication with
321
+# host is allowed. Available since macOS Big Sur 11.0.
322
+#
323
+# @nat66-prefix: The IPv6 prefix to use into guest network. Must be a
324
+# unique local address i.e. start with fd00::/8 and have
325
+# length of 64.
326
+#
327
+# Since: 7.0
328
+##
329
+{ 'struct': 'NetdevVmnetSharedOptions',
330
+ 'data': {
331
+ '*start-address': 'str',
332
+ '*end-address': 'str',
333
+ '*subnet-mask': 'str',
334
+ '*isolated': 'bool',
335
+ '*nat66-prefix': 'str' },
336
+ 'if': 'CONFIG_VMNET' }
337
+
338
+##
339
+# @NetdevVmnetBridgedOptions:
340
+#
341
+# vmnet (bridged mode) network backend.
342
+#
343
+# Bridges the vmnet interface with a physical network interface.
344
+#
345
+# @ifname: The name of the physical interface to be bridged.
346
+#
347
+# @isolated: Enable isolation for this interface. Interface isolation
348
+# ensures that vmnet interface is not able to communicate
349
+# with any other vmnet interfaces. Only communication with
350
+# host is allowed. Available since macOS Big Sur 11.0.
351
+#
352
+# Since: 7.0
353
+##
354
+{ 'struct': 'NetdevVmnetBridgedOptions',
355
+ 'data': {
356
+ 'ifname': 'str',
357
+ '*isolated': 'bool' },
358
+ 'if': 'CONFIG_VMNET' }
359
+
360
+##
361
# @NetClientDriver:
362
#
363
# Available netdev drivers.
364
@@ -XXX,XX +XXX,XX @@
365
# Since: 2.7
366
#
367
# @vhost-vdpa since 5.1
368
+# @vmnet-host since 7.0
369
+# @vmnet-shared since 7.0
370
+# @vmnet-bridged since 7.0
371
##
372
{ 'enum': 'NetClientDriver',
373
'data': [ 'none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde',
374
- 'bridge', 'hubport', 'netmap', 'vhost-user', 'vhost-vdpa' ] }
375
+ 'bridge', 'hubport', 'netmap', 'vhost-user', 'vhost-vdpa',
376
+ { 'name': 'vmnet-host', 'if': 'CONFIG_VMNET' },
377
+ { 'name': 'vmnet-shared', 'if': 'CONFIG_VMNET' },
378
+ { 'name': 'vmnet-bridged', 'if': 'CONFIG_VMNET' }] }
379
380
##
381
# @Netdev:
382
@@ -XXX,XX +XXX,XX @@
383
# Since: 1.2
384
#
385
# 'l2tpv3' - since 2.1
386
+# 'vmnet-host' - since 7.0
387
+# 'vmnet-shared' - since 7.0
388
+# 'vmnet-bridged' - since 7.0
389
##
390
{ 'union': 'Netdev',
391
'base': { 'id': 'str', 'type': 'NetClientDriver' },
392
@@ -XXX,XX +XXX,XX @@
393
'hubport': 'NetdevHubPortOptions',
394
'netmap': 'NetdevNetmapOptions',
395
'vhost-user': 'NetdevVhostUserOptions',
396
- 'vhost-vdpa': 'NetdevVhostVDPAOptions' } }
397
+ 'vhost-vdpa': 'NetdevVhostVDPAOptions',
398
+ 'vmnet-host': { 'type': 'NetdevVmnetHostOptions',
399
+ 'if': 'CONFIG_VMNET' },
400
+ 'vmnet-shared': { 'type': 'NetdevVmnetSharedOptions',
401
+ 'if': 'CONFIG_VMNET' },
402
+ 'vmnet-bridged': { 'type': 'NetdevVmnetBridgedOptions',
403
+ 'if': 'CONFIG_VMNET' } } }
404
405
##
406
# @RxState:
114
--
407
--
115
2.5.0
408
2.7.4
116
409
117
410
diff view generated by jsdifflib
1
From: Zhang Chen <zhangckid@gmail.com>
1
From: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
2
2
3
While do checkpoint, we need to flush all the unhandled packets,
3
Interaction with vmnet.framework in different modes
4
By using the filter notifier mechanism, we can easily to notify
4
differs only on configuration stage, so we can create
5
every compare object to do this process, which runs inside
5
common `send`, `receive`, etc. procedures and reuse them.
6
of compare threads as a coroutine.
6
7
7
vmnet.framework supports iov, but writing more than
8
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
8
one iov into vmnet interface fails with
9
Signed-off-by: Zhang Chen <zhangckid@gmail.com>
9
'VMNET_INVALID_ARGUMENT'. Collecting provided iovs into
10
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
10
one and passing it to vmnet works fine. That's the
11
reason why receive_iov() left unimplemented. But it still
12
works with good enough performance having .receive()
13
implemented only.
14
15
Also, there is no way to unsubscribe from vmnet packages
16
receiving except registering and unregistering event
17
callback or simply drop packages just ignoring and
18
not processing them when related flag is set. Here we do
19
using the second way.
20
21
Signed-off-by: Phillip Tennen <phillip@axleos.com>
22
Signed-off-by: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
23
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
24
---
13
include/migration/colo.h | 6 ++++
25
net/vmnet-common.m | 314 +++++++++++++++++++++++++++++++++++++++++++++++++++++
14
net/colo-compare.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++
26
net/vmnet-shared.c | 83 +++++++++++++-
15
net/colo-compare.h | 22 ++++++++++++++
27
net/vmnet_int.h | 23 ++++
16
3 files changed, 106 insertions(+)
28
3 files changed, 416 insertions(+), 4 deletions(-)
17
create mode 100644 net/colo-compare.h
29
18
30
diff --git a/net/vmnet-common.m b/net/vmnet-common.m
19
diff --git a/include/migration/colo.h b/include/migration/colo.h
20
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
21
--- a/include/migration/colo.h
32
--- a/net/vmnet-common.m
22
+++ b/include/migration/colo.h
33
+++ b/net/vmnet-common.m
23
@@ -XXX,XX +XXX,XX @@
34
@@ -XXX,XX +XXX,XX @@
24
#include "qemu-common.h"
35
*/
25
#include "qapi/qapi-types-migration.h"
36
26
37
#include "qemu/osdep.h"
27
+enum colo_event {
38
+#include "qemu/main-loop.h"
28
+ COLO_EVENT_NONE,
39
+#include "qemu/log.h"
29
+ COLO_EVENT_CHECKPOINT,
40
#include "qapi/qapi-types-net.h"
30
+ COLO_EVENT_FAILOVER,
41
#include "vmnet_int.h"
31
+};
42
#include "clients.h"
32
+
33
void colo_info_init(void);
34
35
void migrate_start_colo_process(MigrationState *s);
36
diff --git a/net/colo-compare.c b/net/colo-compare.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/net/colo-compare.c
39
+++ b/net/colo-compare.c
40
@@ -XXX,XX +XXX,XX @@
43
@@ -XXX,XX +XXX,XX @@
41
#include "qemu/sockets.h"
44
#include "qapi/error.h"
42
#include "colo.h"
45
43
#include "sysemu/iothread.h"
46
#include <vmnet/vmnet.h>
44
+#include "net/colo-compare.h"
47
+#include <dispatch/dispatch.h>
45
+#include "migration/colo.h"
48
+
46
49
+#ifdef DEBUG
47
#define TYPE_COLO_COMPARE "colo-compare"
50
+#define D(x) x
48
#define COLO_COMPARE(obj) \
51
+#define D_LOG(...) qemu_log(__VA_ARGS__)
49
OBJECT_CHECK(CompareState, (obj), TYPE_COLO_COMPARE)
52
+#else
50
53
+#define D(x) do { } while (0)
51
+static QTAILQ_HEAD(, CompareState) net_compares =
54
+#define D_LOG(...) do { } while (0)
52
+ QTAILQ_HEAD_INITIALIZER(net_compares);
55
+#endif
53
+
56
+
54
#define COMPARE_READ_LEN_MAX NET_BUFSIZE
57
+typedef struct vmpktdesc vmpktdesc_t;
55
#define MAX_QUEUE_SIZE 1024
58
+typedef struct iovec iovec_t;
56
59
+
57
@@ -XXX,XX +XXX,XX @@
60
+static void vmnet_set_send_enabled(VmnetCommonState *s, bool enable)
58
/* TODO: Should be configurable */
61
+{
59
#define REGULAR_PACKET_CHECK_MS 3000
62
+ s->send_enabled = enable;
60
63
+}
61
+static QemuMutex event_mtx;
64
+
62
+static QemuCond event_complete_cond;
65
+
63
+static int event_unhandled_count;
66
+static void vmnet_send_completed(NetClientState *nc, ssize_t len)
64
+
67
+{
65
/*
68
+ VmnetCommonState *s = DO_UPCAST(VmnetCommonState, nc, nc);
66
* + CompareState ++
69
+ vmnet_set_send_enabled(s, true);
67
* | |
70
+}
68
@@ -XXX,XX +XXX,XX @@ typedef struct CompareState {
71
+
69
IOThread *iothread;
72
+
70
GMainContext *worker_context;
73
+static void vmnet_send(NetClientState *nc,
71
QEMUTimer *packet_check_timer;
74
+ interface_event_t event_id,
72
+
75
+ xpc_object_t event)
73
+ QEMUBH *event_bh;
76
+{
74
+ enum colo_event event;
77
+ assert(event_id == VMNET_INTERFACE_PACKETS_AVAILABLE);
75
+
78
+
76
+ QTAILQ_ENTRY(CompareState) next;
79
+ VmnetCommonState *s;
77
} CompareState;
80
+ uint64_t packets_available;
78
81
+
79
typedef struct CompareClass {
82
+ struct iovec *iov;
80
@@ -XXX,XX +XXX,XX @@ static void check_old_packet_regular(void *opaque)
83
+ struct vmpktdesc *packets;
81
REGULAR_PACKET_CHECK_MS);
84
+ int pkt_cnt;
82
}
85
+ int i;
83
86
+
84
+/* Public API, Used for COLO frame to notify compare event */
87
+ vmnet_return_t if_status;
85
+void colo_notify_compares_event(void *opaque, int event, Error **errp)
88
+ ssize_t size;
86
+{
89
+
87
+ CompareState *s;
90
+ s = DO_UPCAST(VmnetCommonState, nc, nc);
88
+
91
+
89
+ qemu_mutex_lock(&event_mtx);
92
+ packets_available = xpc_dictionary_get_uint64(
90
+ QTAILQ_FOREACH(s, &net_compares, next) {
93
+ event,
91
+ s->event = event;
94
+ vmnet_estimated_packets_available_key
92
+ qemu_bh_schedule(s->event_bh);
95
+ );
93
+ event_unhandled_count++;
96
+
94
+ }
97
+ pkt_cnt = (packets_available < VMNET_PACKETS_LIMIT) ?
95
+ /* Wait all compare threads to finish handling this event */
98
+ packets_available :
96
+ while (event_unhandled_count > 0) {
99
+ VMNET_PACKETS_LIMIT;
97
+ qemu_cond_wait(&event_complete_cond, &event_mtx);
100
+
98
+ }
101
+
99
+
102
+ iov = s->iov_buf;
100
+ qemu_mutex_unlock(&event_mtx);
103
+ packets = s->packets_buf;
101
+}
104
+
102
+
105
+ for (i = 0; i < pkt_cnt; ++i) {
103
static void colo_compare_timer_init(CompareState *s)
106
+ packets[i].vm_pkt_size = s->max_packet_size;
104
{
107
+ packets[i].vm_pkt_iovcnt = 1;
105
AioContext *ctx = iothread_get_aio_context(s->iothread);
108
+ packets[i].vm_flags = 0;
106
@@ -XXX,XX +XXX,XX @@ static void colo_compare_timer_del(CompareState *s)
109
+ }
107
}
110
+
108
}
111
+ if_status = vmnet_read(s->vmnet_if, packets, &pkt_cnt);
109
112
+ if (if_status != VMNET_SUCCESS) {
110
+static void colo_flush_packets(void *opaque, void *user_data);
113
+ error_printf("vmnet: read failed: %s\n",
111
+
114
+ vmnet_status_map_str(if_status));
112
+static void colo_compare_handle_event(void *opaque)
115
+ }
113
+{
116
+ qemu_mutex_lock_iothread();
114
+ CompareState *s = opaque;
117
+ for (i = 0; i < pkt_cnt; ++i) {
115
+
118
+ size = qemu_send_packet_async(nc,
116
+ switch (s->event) {
119
+ iov[i].iov_base,
117
+ case COLO_EVENT_CHECKPOINT:
120
+ packets[i].vm_pkt_size,
118
+ g_queue_foreach(&s->conn_list, colo_flush_packets, s);
121
+ vmnet_send_completed);
119
+ break;
122
+ if (size == 0) {
120
+ case COLO_EVENT_FAILOVER:
123
+ vmnet_set_send_enabled(s, false);
121
+ break;
124
+ } else if (size < 0) {
122
+ default:
123
+ break;
124
+ }
125
+
126
+ assert(event_unhandled_count > 0);
127
+
128
+ qemu_mutex_lock(&event_mtx);
129
+ event_unhandled_count--;
130
+ qemu_cond_broadcast(&event_complete_cond);
131
+ qemu_mutex_unlock(&event_mtx);
132
+}
133
+
134
static void colo_compare_iothread(CompareState *s)
135
{
136
object_ref(OBJECT(s->iothread));
137
@@ -XXX,XX +XXX,XX @@ static void colo_compare_iothread(CompareState *s)
138
s, s->worker_context, true);
139
140
colo_compare_timer_init(s);
141
+ s->event_bh = qemu_bh_new(colo_compare_handle_event, s);
142
}
143
144
static char *compare_get_pri_indev(Object *obj, Error **errp)
145
@@ -XXX,XX +XXX,XX @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
146
net_socket_rs_init(&s->pri_rs, compare_pri_rs_finalize, s->vnet_hdr);
147
net_socket_rs_init(&s->sec_rs, compare_sec_rs_finalize, s->vnet_hdr);
148
149
+ QTAILQ_INSERT_TAIL(&net_compares, s, next);
150
+
151
g_queue_init(&s->conn_list);
152
153
+ qemu_mutex_init(&event_mtx);
154
+ qemu_cond_init(&event_complete_cond);
155
+
156
s->connection_track_table = g_hash_table_new_full(connection_key_hash,
157
connection_key_equal,
158
g_free,
159
@@ -XXX,XX +XXX,XX @@ static void colo_compare_init(Object *obj)
160
static void colo_compare_finalize(Object *obj)
161
{
162
CompareState *s = COLO_COMPARE(obj);
163
+ CompareState *tmp = NULL;
164
165
qemu_chr_fe_deinit(&s->chr_pri_in, false);
166
qemu_chr_fe_deinit(&s->chr_sec_in, false);
167
@@ -XXX,XX +XXX,XX @@ static void colo_compare_finalize(Object *obj)
168
if (s->iothread) {
169
colo_compare_timer_del(s);
170
}
171
+
172
+ qemu_bh_delete(s->event_bh);
173
+
174
+ QTAILQ_FOREACH(tmp, &net_compares, next) {
175
+ if (tmp == s) {
176
+ QTAILQ_REMOVE(&net_compares, s, next);
177
+ break;
125
+ break;
178
+ }
126
+ }
179
+ }
127
+ }
180
+
128
+ qemu_mutex_unlock_iothread();
181
/* Release all unhandled packets after compare thead exited */
129
+
182
g_queue_foreach(&s->conn_list, colo_flush_packets, s);
130
+}
183
131
+
184
@@ -XXX,XX +XXX,XX @@ static void colo_compare_finalize(Object *obj)
132
+
185
if (s->iothread) {
133
+static void vmnet_register_event_callback(VmnetCommonState *s)
186
object_unref(OBJECT(s->iothread));
134
+{
187
}
135
+ dispatch_queue_t avail_pkt_q = dispatch_queue_create(
188
+
136
+ "org.qemu.vmnet.if_queue",
189
+ qemu_mutex_destroy(&event_mtx);
137
+ DISPATCH_QUEUE_SERIAL
190
+ qemu_cond_destroy(&event_complete_cond);
138
+ );
191
+
139
+
192
g_free(s->pri_indev);
140
+ vmnet_interface_set_event_callback(
193
g_free(s->sec_indev);
141
+ s->vmnet_if,
194
g_free(s->outdev);
142
+ VMNET_INTERFACE_PACKETS_AVAILABLE,
195
diff --git a/net/colo-compare.h b/net/colo-compare.h
143
+ avail_pkt_q,
196
new file mode 100644
144
+ ^(interface_event_t event_id, xpc_object_t event) {
197
index XXXXXXX..XXXXXXX
145
+ if (s->send_enabled) {
198
--- /dev/null
146
+ vmnet_send(&s->nc, event_id, event);
199
+++ b/net/colo-compare.h
147
+ }
148
+ });
149
+}
150
+
151
+
152
+static void vmnet_bufs_init(VmnetCommonState *s)
153
+{
154
+ int i;
155
+ struct vmpktdesc *packets;
156
+ struct iovec *iov;
157
+
158
+ packets = s->packets_buf;
159
+ iov = s->iov_buf;
160
+
161
+ for (i = 0; i < VMNET_PACKETS_LIMIT; ++i) {
162
+ iov[i].iov_len = s->max_packet_size;
163
+ iov[i].iov_base = g_malloc0(iov[i].iov_len);
164
+ packets[i].vm_pkt_iov = iov + i;
165
+ }
166
+}
167
+
168
+
169
+const char *vmnet_status_map_str(vmnet_return_t status)
170
+{
171
+ switch (status) {
172
+ case VMNET_SUCCESS:
173
+ return "success";
174
+ case VMNET_FAILURE:
175
+ return "general failure";
176
+ case VMNET_MEM_FAILURE:
177
+ return "memory allocation failure";
178
+ case VMNET_INVALID_ARGUMENT:
179
+ return "invalid argument specified";
180
+ case VMNET_SETUP_INCOMPLETE:
181
+ return "interface setup is not complete";
182
+ case VMNET_INVALID_ACCESS:
183
+ return "invalid access, permission denied";
184
+ case VMNET_PACKET_TOO_BIG:
185
+ return "packet size is larger than MTU";
186
+ case VMNET_BUFFER_EXHAUSTED:
187
+ return "buffers exhausted in kernel";
188
+ case VMNET_TOO_MANY_PACKETS:
189
+ return "packet count exceeds limit";
190
+#if defined(MAC_OS_VERSION_11_0) && \
191
+ MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_11_0
192
+ case VMNET_SHARING_SERVICE_BUSY:
193
+ return "conflict, sharing service is in use";
194
+#endif
195
+ default:
196
+ return "unknown vmnet error";
197
+ }
198
+}
199
+
200
+
201
+int vmnet_if_create(NetClientState *nc,
202
+ xpc_object_t if_desc,
203
+ Error **errp,
204
+ void (*completion_callback)(xpc_object_t interface_param))
205
+{
206
+ VmnetCommonState *s;
207
+
208
+ dispatch_queue_t if_create_q;
209
+ dispatch_semaphore_t if_created_sem;
210
+
211
+ __block vmnet_return_t if_status;
212
+
213
+ if_create_q = dispatch_queue_create("org.qemu.vmnet.create",
214
+ DISPATCH_QUEUE_SERIAL);
215
+ if_created_sem = dispatch_semaphore_create(0);
216
+
217
+ xpc_dictionary_set_bool(
218
+ if_desc,
219
+ vmnet_allocate_mac_address_key,
220
+ false
221
+ );
222
+
223
+ D(D_LOG("vmnet.start.interface_desc:\n");
224
+ xpc_dictionary_apply(if_desc,
225
+ ^bool(const char *k, xpc_object_t v) {
226
+ char *desc = xpc_copy_description(v);
227
+ D_LOG(" %s=%s\n", k, desc);
228
+ free(desc);
229
+ return true;
230
+ }));
231
+
232
+ s = DO_UPCAST(VmnetCommonState, nc, nc);
233
+ s->vmnet_if = vmnet_start_interface(
234
+ if_desc,
235
+ if_create_q,
236
+ ^(vmnet_return_t status, xpc_object_t interface_param) {
237
+ if_status = status;
238
+ if (status != VMNET_SUCCESS || !interface_param) {
239
+ dispatch_semaphore_signal(if_created_sem);
240
+ return;
241
+ }
242
+
243
+ D(D_LOG("vmnet.start.interface_param:\n");
244
+ xpc_dictionary_apply(interface_param,
245
+ ^bool(const char *k, xpc_object_t v) {
246
+ char *desc = xpc_copy_description(v);
247
+ D_LOG(" %s=%s\n", k, desc);
248
+ free(desc);
249
+ return true;
250
+ }));
251
+
252
+ s->mtu = xpc_dictionary_get_uint64(
253
+ interface_param,
254
+ vmnet_mtu_key);
255
+ s->max_packet_size = xpc_dictionary_get_uint64(
256
+ interface_param,
257
+ vmnet_max_packet_size_key);
258
+
259
+ if (completion_callback) {
260
+ completion_callback(interface_param);
261
+ }
262
+ dispatch_semaphore_signal(if_created_sem);
263
+ });
264
+
265
+ if (s->vmnet_if == NULL) {
266
+ error_setg(errp, "unable to create interface with requested params");
267
+ return -1;
268
+ }
269
+
270
+ dispatch_semaphore_wait(if_created_sem, DISPATCH_TIME_FOREVER);
271
+ dispatch_release(if_create_q);
272
+
273
+ if (if_status != VMNET_SUCCESS) {
274
+ error_setg(errp,
275
+ "cannot create vmnet interface: %s",
276
+ vmnet_status_map_str(if_status));
277
+ return -1;
278
+ }
279
+
280
+ vmnet_register_event_callback(s);
281
+ vmnet_bufs_init(s);
282
+ vmnet_set_send_enabled(s, true);
283
+
284
+ return 0;
285
+}
286
+
287
+
288
+ssize_t vmnet_receive_common(NetClientState *nc,
289
+ const uint8_t *buf,
290
+ size_t size)
291
+{
292
+ VmnetCommonState *s;
293
+ vmpktdesc_t packet;
294
+ iovec_t iov;
295
+ int pkt_cnt;
296
+ vmnet_return_t if_status;
297
+
298
+ s = DO_UPCAST(VmnetCommonState, nc, nc);
299
+
300
+ if (size > s->max_packet_size) {
301
+ warn_report("vmnet: packet is too big, %zu > %llu\n",
302
+ packet.vm_pkt_size,
303
+ s->max_packet_size);
304
+ return -1;
305
+ }
306
+
307
+ iov.iov_base = (char *) buf;
308
+ iov.iov_len = size;
309
+
310
+ packet.vm_pkt_iovcnt = 1;
311
+ packet.vm_flags = 0;
312
+ packet.vm_pkt_size = size;
313
+ packet.vm_pkt_iov = &iov;
314
+
315
+ pkt_cnt = 1;
316
+ if_status = vmnet_write(s->vmnet_if, &packet, &pkt_cnt);
317
+
318
+ if (if_status != VMNET_SUCCESS) {
319
+ error_report("vmnet: write error: %s\n",
320
+ vmnet_status_map_str(if_status));
321
+ }
322
+
323
+ if (if_status == VMNET_SUCCESS && pkt_cnt) {
324
+ return size;
325
+ }
326
+ return 0;
327
+}
328
+
329
+
330
+void vmnet_cleanup_common(NetClientState *nc)
331
+{
332
+ VmnetCommonState *s;
333
+ dispatch_queue_t if_destroy_q;
334
+
335
+ s = DO_UPCAST(VmnetCommonState, nc, nc);
336
+
337
+ qemu_purge_queued_packets(nc);
338
+ vmnet_set_send_enabled(s, false);
339
+
340
+ if (s->vmnet_if == NULL) {
341
+ return;
342
+ }
343
+
344
+ if_destroy_q = dispatch_queue_create(
345
+ "org.qemu.vmnet.destroy",
346
+ DISPATCH_QUEUE_SERIAL
347
+ );
348
+
349
+ vmnet_stop_interface(
350
+ s->vmnet_if,
351
+ if_destroy_q,
352
+ ^(vmnet_return_t status) {
353
+ });
354
+
355
+ for (int i = 0; i < VMNET_PACKETS_LIMIT; ++i) {
356
+ g_free(s->iov_buf[i].iov_base);
357
+ }
358
+}
359
diff --git a/net/vmnet-shared.c b/net/vmnet-shared.c
360
index XXXXXXX..XXXXXXX 100644
361
--- a/net/vmnet-shared.c
362
+++ b/net/vmnet-shared.c
200
@@ -XXX,XX +XXX,XX @@
363
@@ -XXX,XX +XXX,XX @@
201
+/*
364
202
+ * COarse-grain LOck-stepping Virtual Machines for Non-stop Service (COLO)
365
#include "qemu/osdep.h"
203
+ * (a.k.a. Fault Tolerance or Continuous Replication)
366
#include "qapi/qapi-types-net.h"
204
+ *
367
+#include "qapi/error.h"
205
+ * Copyright (c) 2017 HUAWEI TECHNOLOGIES CO., LTD.
368
#include "vmnet_int.h"
206
+ * Copyright (c) 2017 FUJITSU LIMITED
369
#include "clients.h"
207
+ * Copyright (c) 2017 Intel Corporation
370
-#include "qemu/error-report.h"
208
+ *
371
-#include "qapi/error.h"
209
+ * Authors:
372
210
+ * zhanghailiang <zhang.zhanghailiang@huawei.com>
373
#include <vmnet/vmnet.h>
211
+ * Zhang Chen <zhangckid@gmail.com>
374
212
+ *
375
+typedef struct VmnetSharedState {
213
+ * This work is licensed under the terms of the GNU GPL, version 2 or
376
+ VmnetCommonState cs;
214
+ * later. See the COPYING file in the top-level directory.
377
+} VmnetSharedState;
215
+ */
378
+
216
+
379
+
217
+#ifndef QEMU_COLO_COMPARE_H
380
+static xpc_object_t create_if_desc(const Netdev *netdev, Error **errp)
218
+#define QEMU_COLO_COMPARE_H
381
+{
219
+
382
+ const NetdevVmnetSharedOptions *options = &(netdev->u.vmnet_shared);
220
+void colo_notify_compares_event(void *opaque, int event, Error **errp);
383
+ xpc_object_t if_desc = xpc_dictionary_create(NULL, NULL, 0);
221
+
384
+
222
+#endif /* QEMU_COLO_COMPARE_H */
385
+ xpc_dictionary_set_uint64(
386
+ if_desc,
387
+ vmnet_operation_mode_key,
388
+ VMNET_SHARED_MODE
389
+ );
390
+
391
+#if defined(MAC_OS_VERSION_11_0) && \
392
+ MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_11_0
393
+ xpc_dictionary_set_bool(
394
+ if_desc,
395
+ vmnet_enable_isolation_key,
396
+ options->isolated
397
+ );
398
+#else
399
+ if (options->has_isolated) {
400
+ error_setg(errp,
401
+ "vmnet-shared.isolated feature is "
402
+ "unavailable: outdated vmnet.framework API");
403
+ }
404
+#endif
405
+
406
+ if (options->has_nat66_prefix) {
407
+ xpc_dictionary_set_string(if_desc,
408
+ vmnet_nat66_prefix_key,
409
+ options->nat66_prefix);
410
+ }
411
+
412
+ if (options->has_start_address ||
413
+ options->has_end_address ||
414
+ options->has_subnet_mask) {
415
+
416
+ if (options->has_start_address &&
417
+ options->has_end_address &&
418
+ options->has_subnet_mask) {
419
+
420
+ xpc_dictionary_set_string(if_desc,
421
+ vmnet_start_address_key,
422
+ options->start_address);
423
+ xpc_dictionary_set_string(if_desc,
424
+ vmnet_end_address_key,
425
+ options->end_address);
426
+ xpc_dictionary_set_string(if_desc,
427
+ vmnet_subnet_mask_key,
428
+ options->subnet_mask);
429
+ } else {
430
+ error_setg(
431
+ errp,
432
+ "'start-address', 'end-address', 'subnet-mask' "
433
+ "should be provided together"
434
+ );
435
+ }
436
+ }
437
+
438
+ return if_desc;
439
+}
440
+
441
+static NetClientInfo net_vmnet_shared_info = {
442
+ .type = NET_CLIENT_DRIVER_VMNET_SHARED,
443
+ .size = sizeof(VmnetSharedState),
444
+ .receive = vmnet_receive_common,
445
+ .cleanup = vmnet_cleanup_common,
446
+};
447
+
448
int net_init_vmnet_shared(const Netdev *netdev, const char *name,
449
NetClientState *peer, Error **errp)
450
{
451
- error_setg(errp, "vmnet-shared is not implemented yet");
452
- return -1;
453
+ NetClientState *nc = qemu_new_net_client(&net_vmnet_shared_info,
454
+ peer, "vmnet-shared", name);
455
+ xpc_object_t if_desc = create_if_desc(netdev, errp);
456
+
457
+ return vmnet_if_create(nc, if_desc, errp, NULL);
458
}
459
diff --git a/net/vmnet_int.h b/net/vmnet_int.h
460
index XXXXXXX..XXXXXXX 100644
461
--- a/net/vmnet_int.h
462
+++ b/net/vmnet_int.h
463
@@ -XXX,XX +XXX,XX @@
464
465
#include <vmnet/vmnet.h>
466
467
+#define VMNET_PACKETS_LIMIT 50
468
+
469
typedef struct VmnetCommonState {
470
NetClientState nc;
471
+ interface_ref vmnet_if;
472
+
473
+ bool send_enabled;
474
+
475
+ uint64_t mtu;
476
+ uint64_t max_packet_size;
477
+
478
+ struct vmpktdesc packets_buf[VMNET_PACKETS_LIMIT];
479
+ struct iovec iov_buf[VMNET_PACKETS_LIMIT];
480
481
} VmnetCommonState;
482
483
+const char *vmnet_status_map_str(vmnet_return_t status);
484
+
485
+int vmnet_if_create(NetClientState *nc,
486
+ xpc_object_t if_desc,
487
+ Error **errp,
488
+ void (*completion_callback)(xpc_object_t interface_param));
489
+
490
+ssize_t vmnet_receive_common(NetClientState *nc,
491
+ const uint8_t *buf,
492
+ size_t size);
493
+
494
+void vmnet_cleanup_common(NetClientState *nc);
495
496
#endif /* VMNET_INT_H */
223
--
497
--
224
2.5.0
498
2.7.4
225
499
226
500
diff view generated by jsdifflib
Deleted patch
1
From: Zhang Chen <zhangckid@gmail.com>
2
1
3
Make sure master start block replication after slave's block
4
replication started.
5
6
Besides, we need to activate VM's blocks before goes into
7
COLO state.
8
9
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
10
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
11
Signed-off-by: Zhang Chen <zhangckid@gmail.com>
12
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
13
Signed-off-by: Jason Wang <jasowang@redhat.com>
14
---
15
migration/colo.c | 43 +++++++++++++++++++++++++++++++++++++++++++
16
migration/migration.c | 10 ++++++++++
17
2 files changed, 53 insertions(+)
18
19
diff --git a/migration/colo.c b/migration/colo.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/migration/colo.c
22
+++ b/migration/colo.c
23
@@ -XXX,XX +XXX,XX @@
24
#include "replication.h"
25
#include "net/colo-compare.h"
26
#include "net/colo.h"
27
+#include "block/block.h"
28
29
static bool vmstate_loading;
30
static Notifier packets_compare_notifier;
31
@@ -XXX,XX +XXX,XX @@ static void secondary_vm_do_failover(void)
32
{
33
int old_state;
34
MigrationIncomingState *mis = migration_incoming_get_current();
35
+ Error *local_err = NULL;
36
37
/* Can not do failover during the process of VM's loading VMstate, Or
38
* it will break the secondary VM.
39
@@ -XXX,XX +XXX,XX @@ static void secondary_vm_do_failover(void)
40
migrate_set_state(&mis->state, MIGRATION_STATUS_COLO,
41
MIGRATION_STATUS_COMPLETED);
42
43
+ replication_stop_all(true, &local_err);
44
+ if (local_err) {
45
+ error_report_err(local_err);
46
+ }
47
+
48
if (!autostart) {
49
error_report("\"-S\" qemu option will be ignored in secondary side");
50
/* recover runstate to normal migration finish state */
51
@@ -XXX,XX +XXX,XX @@ static void primary_vm_do_failover(void)
52
{
53
MigrationState *s = migrate_get_current();
54
int old_state;
55
+ Error *local_err = NULL;
56
57
migrate_set_state(&s->state, MIGRATION_STATUS_COLO,
58
MIGRATION_STATUS_COMPLETED);
59
@@ -XXX,XX +XXX,XX @@ static void primary_vm_do_failover(void)
60
FailoverStatus_str(old_state));
61
return;
62
}
63
+
64
+ replication_stop_all(true, &local_err);
65
+ if (local_err) {
66
+ error_report_err(local_err);
67
+ local_err = NULL;
68
+ }
69
+
70
/* Notify COLO thread that failover work is finished */
71
qemu_sem_post(&s->colo_exit_sem);
72
}
73
@@ -XXX,XX +XXX,XX @@ static int colo_do_checkpoint_transaction(MigrationState *s,
74
qemu_savevm_state_header(fb);
75
qemu_savevm_state_setup(fb);
76
qemu_mutex_lock_iothread();
77
+ replication_do_checkpoint_all(&local_err);
78
+ if (local_err) {
79
+ qemu_mutex_unlock_iothread();
80
+ goto out;
81
+ }
82
qemu_savevm_state_complete_precopy(fb, false, false);
83
qemu_mutex_unlock_iothread();
84
85
@@ -XXX,XX +XXX,XX @@ static void colo_process_checkpoint(MigrationState *s)
86
object_unref(OBJECT(bioc));
87
88
qemu_mutex_lock_iothread();
89
+ replication_start_all(REPLICATION_MODE_PRIMARY, &local_err);
90
+ if (local_err) {
91
+ qemu_mutex_unlock_iothread();
92
+ goto out;
93
+ }
94
+
95
vm_start();
96
qemu_mutex_unlock_iothread();
97
trace_colo_vm_state_change("stop", "run");
98
@@ -XXX,XX +XXX,XX @@ void *colo_process_incoming_thread(void *opaque)
99
object_unref(OBJECT(bioc));
100
101
qemu_mutex_lock_iothread();
102
+ replication_start_all(REPLICATION_MODE_SECONDARY, &local_err);
103
+ if (local_err) {
104
+ qemu_mutex_unlock_iothread();
105
+ goto out;
106
+ }
107
vm_start();
108
trace_colo_vm_state_change("stop", "run");
109
qemu_mutex_unlock_iothread();
110
@@ -XXX,XX +XXX,XX @@ void *colo_process_incoming_thread(void *opaque)
111
goto out;
112
}
113
114
+ replication_get_error_all(&local_err);
115
+ if (local_err) {
116
+ qemu_mutex_unlock_iothread();
117
+ goto out;
118
+ }
119
+ /* discard colo disk buffer */
120
+ replication_do_checkpoint_all(&local_err);
121
+ if (local_err) {
122
+ qemu_mutex_unlock_iothread();
123
+ goto out;
124
+ }
125
+
126
vmstate_loading = false;
127
vm_start();
128
trace_colo_vm_state_change("stop", "run");
129
diff --git a/migration/migration.c b/migration/migration.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/migration/migration.c
132
+++ b/migration/migration.c
133
@@ -XXX,XX +XXX,XX @@ static void process_incoming_migration_co(void *opaque)
134
MigrationIncomingState *mis = migration_incoming_get_current();
135
PostcopyState ps;
136
int ret;
137
+ Error *local_err = NULL;
138
139
assert(mis->from_src_file);
140
mis->migration_incoming_co = qemu_coroutine_self();
141
@@ -XXX,XX +XXX,XX @@ static void process_incoming_migration_co(void *opaque)
142
143
/* we get COLO info, and know if we are in COLO mode */
144
if (!ret && migration_incoming_enable_colo()) {
145
+ /* Make sure all file formats flush their mutable metadata */
146
+ bdrv_invalidate_cache_all(&local_err);
147
+ if (local_err) {
148
+ migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE,
149
+ MIGRATION_STATUS_FAILED);
150
+ error_report_err(local_err);
151
+ exit(EXIT_FAILURE);
152
+ }
153
+
154
qemu_thread_create(&mis->colo_incoming_thread, "COLO incoming",
155
colo_process_incoming_thread, mis, QEMU_THREAD_JOINABLE);
156
mis->have_colo_incoming_thread = true;
157
--
158
2.5.0
159
160
diff view generated by jsdifflib
1
From: Zhang Chen <zhangckid@gmail.com>
1
From: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
2
2
3
We should not load PVM's state directly into SVM, because there maybe some
3
Signed-off-by: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
4
errors happen when SVM is receving data, which will break SVM.
5
6
We need to ensure receving all data before load the state into SVM. We use
7
an extra memory to cache these data (PVM's ram). The ram cache in secondary side
8
is initially the same as SVM/PVM's memory. And in the process of checkpoint,
9
we cache the dirty pages of PVM into this ram cache firstly, so this ram cache
10
always the same as PVM's memory at every checkpoint, then we flush this cached ram
11
to SVM after we receive all PVM's state.
12
13
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
14
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
15
Signed-off-by: Zhang Chen <zhangckid@gmail.com>
16
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
17
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
18
Signed-off-by: Jason Wang <jasowang@redhat.com>
4
Signed-off-by: Jason Wang <jasowang@redhat.com>
19
---
5
---
20
include/exec/ram_addr.h | 1 +
6
net/vmnet-host.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
21
migration/migration.c | 7 +++++
7
1 file changed, 104 insertions(+), 6 deletions(-)
22
migration/ram.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++--
23
migration/ram.h | 4 +++
24
migration/savevm.c | 2 +-
25
5 files changed, 94 insertions(+), 3 deletions(-)
26
8
27
diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
9
diff --git a/net/vmnet-host.c b/net/vmnet-host.c
28
index XXXXXXX..XXXXXXX 100644
10
index XXXXXXX..XXXXXXX 100644
29
--- a/include/exec/ram_addr.h
11
--- a/net/vmnet-host.c
30
+++ b/include/exec/ram_addr.h
12
+++ b/net/vmnet-host.c
31
@@ -XXX,XX +XXX,XX @@ struct RAMBlock {
13
@@ -XXX,XX +XXX,XX @@
32
struct rcu_head rcu;
14
*/
33
struct MemoryRegion *mr;
15
34
uint8_t *host;
16
#include "qemu/osdep.h"
35
+ uint8_t *colo_cache; /* For colo, VM's ram cache */
17
+#include "qemu/uuid.h"
36
ram_addr_t offset;
18
#include "qapi/qapi-types-net.h"
37
ram_addr_t used_length;
19
-#include "vmnet_int.h"
38
ram_addr_t max_length;
20
-#include "clients.h"
39
diff --git a/migration/migration.c b/migration/migration.c
21
-#include "qemu/error-report.h"
40
index XXXXXXX..XXXXXXX 100644
22
#include "qapi/error.h"
41
--- a/migration/migration.c
23
+#include "clients.h"
42
+++ b/migration/migration.c
24
+#include "vmnet_int.h"
43
@@ -XXX,XX +XXX,XX @@ static void process_incoming_migration_co(void *opaque)
25
44
exit(EXIT_FAILURE);
26
#include <vmnet/vmnet.h>
45
}
27
46
28
+typedef struct VmnetHostState {
47
+ if (colo_init_ram_cache() < 0) {
29
+ VmnetCommonState cs;
48
+ error_report("Init ram cache failed");
30
+ QemuUUID network_uuid;
49
+ exit(EXIT_FAILURE);
31
+} VmnetHostState;
32
+
33
+static xpc_object_t create_if_desc(const Netdev *netdev,
34
+ NetClientState *nc,
35
+ Error **errp)
36
+{
37
+ const NetdevVmnetHostOptions *options = &(netdev->u.vmnet_host);
38
+
39
+ xpc_object_t if_desc = xpc_dictionary_create(NULL, NULL, 0);
40
+
41
+ xpc_dictionary_set_uint64(
42
+ if_desc,
43
+ vmnet_operation_mode_key,
44
+ VMNET_HOST_MODE
45
+ );
46
+
47
+#if defined(MAC_OS_VERSION_11_0) && \
48
+ MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_11_0
49
+
50
+ VmnetCommonState *cs = DO_UPCAST(VmnetCommonState, nc, nc);
51
+ VmnetHostState *hs = DO_UPCAST(VmnetHostState, cs, cs);
52
+
53
+ xpc_dictionary_set_bool(
54
+ if_desc,
55
+ vmnet_enable_isolation_key,
56
+ options->isolated
57
+ );
58
+
59
+ if (options->has_net_uuid) {
60
+ if (qemu_uuid_parse(options->net_uuid, &hs->network_uuid) < 0) {
61
+ error_setg(errp, "Invalid UUID provided in 'net-uuid'");
50
+ }
62
+ }
51
+
63
+
52
qemu_thread_create(&mis->colo_incoming_thread, "COLO incoming",
64
+ xpc_dictionary_set_uuid(
53
colo_process_incoming_thread, mis, QEMU_THREAD_JOINABLE);
65
+ if_desc,
54
mis->have_colo_incoming_thread = true;
66
+ vmnet_network_identifier_key,
55
@@ -XXX,XX +XXX,XX @@ static void process_incoming_migration_co(void *opaque)
67
+ hs->network_uuid.data
56
68
+ );
57
/* Wait checkpoint incoming thread exit before free resource */
58
qemu_thread_join(&mis->colo_incoming_thread);
59
+ /* We hold the global iothread lock, so it is safe here */
60
+ colo_release_ram_cache();
61
}
62
63
if (ret < 0) {
64
diff --git a/migration/ram.c b/migration/ram.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/migration/ram.c
67
+++ b/migration/ram.c
68
@@ -XXX,XX +XXX,XX @@ static inline void *host_from_ram_block_offset(RAMBlock *block,
69
return block->host + offset;
70
}
71
72
+static inline void *colo_cache_from_block_offset(RAMBlock *block,
73
+ ram_addr_t offset)
74
+{
75
+ if (!offset_in_ramblock(block, offset)) {
76
+ return NULL;
77
+ }
69
+ }
78
+ if (!block->colo_cache) {
70
+#else
79
+ error_report("%s: colo_cache is NULL in block :%s",
71
+ if (options->has_isolated) {
80
+ __func__, block->idstr);
72
+ error_setg(errp,
81
+ return NULL;
73
+ "vmnet-host.isolated feature is "
74
+ "unavailable: outdated vmnet.framework API");
82
+ }
75
+ }
83
+ return block->colo_cache + offset;
84
+}
85
+
76
+
86
/**
77
+ if (options->has_net_uuid) {
87
* ram_handle_compressed: handle the zero page case
78
+ error_setg(errp,
88
*
79
+ "vmnet-host.net-uuid feature is "
89
@@ -XXX,XX +XXX,XX @@ static void decompress_data_with_multi_threads(QEMUFile *f,
80
+ "unavailable: outdated vmnet.framework API");
90
qemu_mutex_unlock(&decomp_done_lock);
81
+ }
91
}
82
+#endif
92
93
+/*
94
+ * colo cache: this is for secondary VM, we cache the whole
95
+ * memory of the secondary VM, it is need to hold the global lock
96
+ * to call this helper.
97
+ */
98
+int colo_init_ram_cache(void)
99
+{
100
+ RAMBlock *block;
101
+
83
+
102
+ rcu_read_lock();
84
+ if (options->has_start_address ||
103
+ QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
85
+ options->has_end_address ||
104
+ block->colo_cache = qemu_anon_ram_alloc(block->used_length,
86
+ options->has_subnet_mask) {
105
+ NULL,
106
+ false);
107
+ if (!block->colo_cache) {
108
+ error_report("%s: Can't alloc memory for COLO cache of block %s,"
109
+ "size 0x" RAM_ADDR_FMT, __func__, block->idstr,
110
+ block->used_length);
111
+ goto out_locked;
112
+ }
113
+ memcpy(block->colo_cache, block->host, block->used_length);
114
+ }
115
+ rcu_read_unlock();
116
+ return 0;
117
+
87
+
118
+out_locked:
88
+ if (options->has_start_address &&
119
+ QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
89
+ options->has_end_address &&
120
+ if (block->colo_cache) {
90
+ options->has_subnet_mask) {
121
+ qemu_anon_ram_free(block->colo_cache, block->used_length);
91
+
122
+ block->colo_cache = NULL;
92
+ xpc_dictionary_set_string(if_desc,
93
+ vmnet_start_address_key,
94
+ options->start_address);
95
+ xpc_dictionary_set_string(if_desc,
96
+ vmnet_end_address_key,
97
+ options->end_address);
98
+ xpc_dictionary_set_string(if_desc,
99
+ vmnet_subnet_mask_key,
100
+ options->subnet_mask);
101
+ } else {
102
+ error_setg(
103
+ errp,
104
+ "'start-address', 'end-address', 'subnet-mask' "
105
+ "should be provided together"
106
+ );
123
+ }
107
+ }
124
+ }
108
+ }
125
+
109
+
126
+ rcu_read_unlock();
110
+ return if_desc;
127
+ return -errno;
128
+}
111
+}
129
+
112
+
130
+/* It is need to hold the global lock to call this helper */
113
+static NetClientInfo net_vmnet_host_info = {
131
+void colo_release_ram_cache(void)
114
+ .type = NET_CLIENT_DRIVER_VMNET_HOST,
115
+ .size = sizeof(VmnetHostState),
116
+ .receive = vmnet_receive_common,
117
+ .cleanup = vmnet_cleanup_common,
118
+};
119
+
120
int net_init_vmnet_host(const Netdev *netdev, const char *name,
121
- NetClientState *peer, Error **errp) {
122
- error_setg(errp, "vmnet-host is not implemented yet");
123
- return -1;
124
+ NetClientState *peer, Error **errp)
132
+{
125
+{
133
+ RAMBlock *block;
126
+ NetClientState *nc;
127
+ xpc_object_t if_desc;
134
+
128
+
135
+ rcu_read_lock();
129
+ nc = qemu_new_net_client(&net_vmnet_host_info,
136
+ QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
130
+ peer, "vmnet-host", name);
137
+ if (block->colo_cache) {
131
+ if_desc = create_if_desc(netdev, nc, errp);
138
+ qemu_anon_ram_free(block->colo_cache, block->used_length);
132
+ return vmnet_if_create(nc, if_desc, errp, NULL);
139
+ block->colo_cache = NULL;
140
+ }
141
+ }
142
+ rcu_read_unlock();
143
+}
144
+
145
/**
146
* ram_load_setup: Setup RAM for migration incoming side
147
*
148
@@ -XXX,XX +XXX,XX @@ static int ram_load_setup(QEMUFile *f, void *opaque)
149
150
xbzrle_load_setup();
151
ramblock_recv_map_init();
152
+
153
return 0;
154
}
133
}
155
156
@@ -XXX,XX +XXX,XX @@ static int ram_load_cleanup(void *opaque)
157
g_free(rb->receivedmap);
158
rb->receivedmap = NULL;
159
}
160
+
161
return 0;
162
}
163
164
@@ -XXX,XX +XXX,XX @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
165
RAM_SAVE_FLAG_COMPRESS_PAGE | RAM_SAVE_FLAG_XBZRLE)) {
166
RAMBlock *block = ram_block_from_stream(f, flags);
167
168
- host = host_from_ram_block_offset(block, addr);
169
+ /*
170
+ * After going into COLO, we should load the Page into colo_cache.
171
+ */
172
+ if (migration_incoming_in_colo_state()) {
173
+ host = colo_cache_from_block_offset(block, addr);
174
+ } else {
175
+ host = host_from_ram_block_offset(block, addr);
176
+ }
177
if (!host) {
178
error_report("Illegal RAM offset " RAM_ADDR_FMT, addr);
179
ret = -EINVAL;
180
break;
181
}
182
- ramblock_recv_bitmap_set(block, host);
183
+
184
+ if (!migration_incoming_in_colo_state()) {
185
+ ramblock_recv_bitmap_set(block, host);
186
+ }
187
+
188
trace_ram_load_loop(block->idstr, (uint64_t)addr, flags, host);
189
}
190
191
diff --git a/migration/ram.h b/migration/ram.h
192
index XXXXXXX..XXXXXXX 100644
193
--- a/migration/ram.h
194
+++ b/migration/ram.h
195
@@ -XXX,XX +XXX,XX @@ int64_t ramblock_recv_bitmap_send(QEMUFile *file,
196
const char *block_name);
197
int ram_dirty_bitmap_reload(MigrationState *s, RAMBlock *rb);
198
199
+/* ram cache */
200
+int colo_init_ram_cache(void);
201
+void colo_release_ram_cache(void);
202
+
203
#endif
204
diff --git a/migration/savevm.c b/migration/savevm.c
205
index XXXXXXX..XXXXXXX 100644
206
--- a/migration/savevm.c
207
+++ b/migration/savevm.c
208
@@ -XXX,XX +XXX,XX @@ static int loadvm_handle_recv_bitmap(MigrationIncomingState *mis,
209
static int loadvm_process_enable_colo(MigrationIncomingState *mis)
210
{
211
migration_incoming_enable_colo();
212
- return 0;
213
+ return colo_init_ram_cache();
214
}
215
216
/*
217
--
134
--
218
2.5.0
135
2.7.4
219
136
220
137
diff view generated by jsdifflib
1
From: Zhang Chen <zhangckid@gmail.com>
1
From: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
2
2
3
We need to know if migration is going into COLO state for
3
Signed-off-by: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
4
incoming side before start normal migration.
5
6
Instead by using the VMStateDescription to send colo_state
7
from source side to destination side, we use MIG_CMD_ENABLE_COLO
8
to indicate whether COLO is enabled or not.
9
10
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
11
Signed-off-by: Zhang Chen <zhangckid@gmail.com>
12
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
13
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
14
Signed-off-by: Jason Wang <jasowang@redhat.com>
4
Signed-off-by: Jason Wang <jasowang@redhat.com>
15
---
5
---
16
include/migration/colo.h | 5 ++--
6
net/vmnet-bridged.m | 105 +++++++++++++++++++++++++++++++++++++++++++++++++---
17
migration/Makefile.objs | 2 +-
7
1 file changed, 100 insertions(+), 5 deletions(-)
18
migration/colo-comm.c | 76 ------------------------------------------------
19
migration/colo.c | 13 ++++++++-
20
migration/migration.c | 23 ++++++++++++++-
21
migration/savevm.c | 17 +++++++++++
22
migration/savevm.h | 1 +
23
migration/trace-events | 1 +
24
vl.c | 2 --
25
9 files changed, 57 insertions(+), 83 deletions(-)
26
delete mode 100644 migration/colo-comm.c
27
8
28
diff --git a/include/migration/colo.h b/include/migration/colo.h
9
diff --git a/net/vmnet-bridged.m b/net/vmnet-bridged.m
29
index XXXXXXX..XXXXXXX 100644
10
index XXXXXXX..XXXXXXX 100644
30
--- a/include/migration/colo.h
11
--- a/net/vmnet-bridged.m
31
+++ b/include/migration/colo.h
12
+++ b/net/vmnet-bridged.m
32
@@ -XXX,XX +XXX,XX @@ void migrate_start_colo_process(MigrationState *s);
33
bool migration_in_colo_state(void);
34
35
/* loadvm */
36
-bool migration_incoming_enable_colo(void);
37
-void migration_incoming_exit_colo(void);
38
+void migration_incoming_enable_colo(void);
39
+void migration_incoming_disable_colo(void);
40
+bool migration_incoming_colo_enabled(void);
41
void *colo_process_incoming_thread(void *opaque);
42
bool migration_incoming_in_colo_state(void);
43
44
diff --git a/migration/Makefile.objs b/migration/Makefile.objs
45
index XXXXXXX..XXXXXXX 100644
46
--- a/migration/Makefile.objs
47
+++ b/migration/Makefile.objs
48
@@ -XXX,XX +XXX,XX @@
13
@@ -XXX,XX +XXX,XX @@
49
common-obj-y += migration.o socket.o fd.o exec.o
14
50
common-obj-y += tls.o channel.o savevm.o
15
#include "qemu/osdep.h"
51
-common-obj-y += colo-comm.o colo.o colo-failover.o
16
#include "qapi/qapi-types-net.h"
52
+common-obj-y += colo.o colo-failover.o
17
-#include "vmnet_int.h"
53
common-obj-y += vmstate.o vmstate-types.o page_cache.o
18
-#include "clients.h"
54
common-obj-y += qemu-file.o global_state.o
19
-#include "qemu/error-report.h"
55
common-obj-y += qemu-file-channel.o
20
#include "qapi/error.h"
56
diff --git a/migration/colo-comm.c b/migration/colo-comm.c
21
+#include "clients.h"
57
deleted file mode 100644
22
+#include "vmnet_int.h"
58
index XXXXXXX..XXXXXXX
23
59
--- a/migration/colo-comm.c
24
#include <vmnet/vmnet.h>
60
+++ /dev/null
25
61
@@ -XXX,XX +XXX,XX @@
26
+typedef struct VmnetBridgedState {
62
-/*
27
+ VmnetCommonState cs;
63
- * COarse-grain LOck-stepping Virtual Machines for Non-stop Service (COLO)
28
+} VmnetBridgedState;
64
- * (a.k.a. Fault Tolerance or Continuous Replication)
29
+
65
- *
30
+static bool validate_ifname(const char *ifname)
66
- * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
67
- * Copyright (c) 2016 FUJITSU LIMITED
68
- * Copyright (c) 2016 Intel Corporation
69
- *
70
- * This work is licensed under the terms of the GNU GPL, version 2 or
71
- * later. See the COPYING file in the top-level directory.
72
- *
73
- */
74
-
75
-#include "qemu/osdep.h"
76
-#include "migration.h"
77
-#include "migration/colo.h"
78
-#include "migration/vmstate.h"
79
-#include "trace.h"
80
-
81
-typedef struct {
82
- bool colo_requested;
83
-} COLOInfo;
84
-
85
-static COLOInfo colo_info;
86
-
87
-COLOMode get_colo_mode(void)
88
-{
89
- if (migration_in_colo_state()) {
90
- return COLO_MODE_PRIMARY;
91
- } else if (migration_incoming_in_colo_state()) {
92
- return COLO_MODE_SECONDARY;
93
- } else {
94
- return COLO_MODE_UNKNOWN;
95
- }
96
-}
97
-
98
-static int colo_info_pre_save(void *opaque)
99
-{
100
- COLOInfo *s = opaque;
101
-
102
- s->colo_requested = migrate_colo_enabled();
103
-
104
- return 0;
105
-}
106
-
107
-static bool colo_info_need(void *opaque)
108
-{
109
- return migrate_colo_enabled();
110
-}
111
-
112
-static const VMStateDescription colo_state = {
113
- .name = "COLOState",
114
- .version_id = 1,
115
- .minimum_version_id = 1,
116
- .pre_save = colo_info_pre_save,
117
- .needed = colo_info_need,
118
- .fields = (VMStateField[]) {
119
- VMSTATE_BOOL(colo_requested, COLOInfo),
120
- VMSTATE_END_OF_LIST()
121
- },
122
-};
123
-
124
-void colo_info_init(void)
125
-{
126
- vmstate_register(NULL, 0, &colo_state, &colo_info);
127
-}
128
-
129
-bool migration_incoming_enable_colo(void)
130
-{
131
- return colo_info.colo_requested;
132
-}
133
-
134
-void migration_incoming_exit_colo(void)
135
-{
136
- colo_info.colo_requested = false;
137
-}
138
diff --git a/migration/colo.c b/migration/colo.c
139
index XXXXXXX..XXXXXXX 100644
140
--- a/migration/colo.c
141
+++ b/migration/colo.c
142
@@ -XXX,XX +XXX,XX @@ static void primary_vm_do_failover(void)
143
qemu_sem_post(&s->colo_exit_sem);
144
}
145
146
+COLOMode get_colo_mode(void)
147
+{
31
+{
148
+ if (migration_in_colo_state()) {
32
+ xpc_object_t shared_if_list = vmnet_copy_shared_interface_list();
149
+ return COLO_MODE_PRIMARY;
33
+ __block bool match = false;
150
+ } else if (migration_incoming_in_colo_state()) {
34
+
151
+ return COLO_MODE_SECONDARY;
35
+ xpc_array_apply(
152
+ } else {
36
+ shared_if_list,
153
+ return COLO_MODE_UNKNOWN;
37
+ ^bool(size_t index, xpc_object_t value) {
154
+ }
38
+ if (strcmp(xpc_string_get_string_ptr(value), ifname) == 0) {
39
+ match = true;
40
+ return false;
41
+ }
42
+ return true;
43
+ });
44
+
45
+ return match;
155
+}
46
+}
156
+
47
+
157
void colo_do_failover(MigrationState *s)
48
+static const char *get_valid_ifnames(void)
158
{
159
/* Make sure VM stopped while failover happened. */
160
@@ -XXX,XX +XXX,XX @@ out:
161
if (mis->to_src_file) {
162
qemu_fclose(mis->to_src_file);
163
}
164
- migration_incoming_exit_colo();
165
+ migration_incoming_disable_colo();
166
167
rcu_unregister_thread();
168
return NULL;
169
diff --git a/migration/migration.c b/migration/migration.c
170
index XXXXXXX..XXXXXXX 100644
171
--- a/migration/migration.c
172
+++ b/migration/migration.c
173
@@ -XXX,XX +XXX,XX @@ int migrate_send_rp_req_pages(MigrationIncomingState *mis, const char *rbname,
174
return migrate_send_rp_message(mis, msg_type, msglen, bufc);
175
}
176
177
+static bool migration_colo_enabled;
178
+bool migration_incoming_colo_enabled(void)
179
+{
49
+{
180
+ return migration_colo_enabled;
50
+ xpc_object_t shared_if_list = vmnet_copy_shared_interface_list();
51
+ __block char *if_list = NULL;
52
+
53
+ xpc_array_apply(
54
+ shared_if_list,
55
+ ^bool(size_t index, xpc_object_t value) {
56
+ if_list = g_strconcat(xpc_string_get_string_ptr(value),
57
+ " ",
58
+ if_list,
59
+ NULL);
60
+ return true;
61
+ });
62
+
63
+ if (if_list) {
64
+ return if_list;
65
+ }
66
+ return "[no interfaces]";
181
+}
67
+}
182
+
68
+
183
+void migration_incoming_disable_colo(void)
69
+static xpc_object_t create_if_desc(const Netdev *netdev, Error **errp)
184
+{
70
+{
185
+ migration_colo_enabled = false;
71
+ const NetdevVmnetBridgedOptions *options = &(netdev->u.vmnet_bridged);
72
+ xpc_object_t if_desc = xpc_dictionary_create(NULL, NULL, 0);
73
+
74
+ xpc_dictionary_set_uint64(
75
+ if_desc,
76
+ vmnet_operation_mode_key,
77
+ VMNET_BRIDGED_MODE
78
+ );
79
+
80
+#if defined(MAC_OS_VERSION_11_0) && \
81
+ MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_11_0
82
+ xpc_dictionary_set_bool(
83
+ if_desc,
84
+ vmnet_enable_isolation_key,
85
+ options->isolated
86
+ );
87
+#else
88
+ if (options->has_isolated) {
89
+ error_setg(errp,
90
+ "vmnet-bridged.isolated feature is "
91
+ "unavailable: outdated vmnet.framework API");
92
+ }
93
+#endif
94
+
95
+ if (validate_ifname(options->ifname)) {
96
+ xpc_dictionary_set_string(if_desc,
97
+ vmnet_shared_interface_name_key,
98
+ options->ifname);
99
+ } else {
100
+ return NULL;
101
+ }
102
+ return if_desc;
186
+}
103
+}
187
+
104
+
188
+void migration_incoming_enable_colo(void)
105
+static NetClientInfo net_vmnet_bridged_info = {
189
+{
106
+ .type = NET_CLIENT_DRIVER_VMNET_BRIDGED,
190
+ migration_colo_enabled = true;
107
+ .size = sizeof(VmnetBridgedState),
191
+}
108
+ .receive = vmnet_receive_common,
109
+ .cleanup = vmnet_cleanup_common,
110
+};
192
+
111
+
193
void qemu_start_incoming_migration(const char *uri, Error **errp)
112
int net_init_vmnet_bridged(const Netdev *netdev, const char *name,
113
NetClientState *peer, Error **errp)
194
{
114
{
195
const char *p;
115
- error_setg(errp, "vmnet-bridged is not implemented yet");
196
@@ -XXX,XX +XXX,XX @@ static void process_incoming_migration_co(void *opaque)
116
- return -1;
197
}
117
+ NetClientState *nc = qemu_new_net_client(&net_vmnet_bridged_info,
198
118
+ peer, "vmnet-bridged", name);
199
/* we get COLO info, and know if we are in COLO mode */
119
+ xpc_object_t if_desc = create_if_desc(netdev, errp);;
200
- if (!ret && migration_incoming_enable_colo()) {
120
+
201
+ if (!ret && migration_incoming_colo_enabled()) {
121
+ if (!if_desc) {
202
/* Make sure all file formats flush their mutable metadata */
122
+ error_setg(errp,
203
bdrv_invalidate_cache_all(&local_err);
123
+ "unsupported ifname, should be one of: %s",
204
if (local_err) {
124
+ get_valid_ifnames());
205
@@ -XXX,XX +XXX,XX @@ static void *migration_thread(void *opaque)
125
+ return -1;
206
qemu_savevm_send_postcopy_advise(s->to_dst_file);
207
}
208
209
+ if (migrate_colo_enabled()) {
210
+ /* Notify migration destination that we enable COLO */
211
+ qemu_savevm_send_colo_enable(s->to_dst_file);
212
+ }
126
+ }
213
+
127
+
214
qemu_savevm_state_setup(s->to_dst_file);
128
+ return vmnet_if_create(nc, if_desc, errp, NULL);
215
216
s->setup_time = qemu_clock_get_ms(QEMU_CLOCK_HOST) - setup_start;
217
diff --git a/migration/savevm.c b/migration/savevm.c
218
index XXXXXXX..XXXXXXX 100644
219
--- a/migration/savevm.c
220
+++ b/migration/savevm.c
221
@@ -XXX,XX +XXX,XX @@
222
#include "io/channel-file.h"
223
#include "sysemu/replay.h"
224
#include "qjson.h"
225
+#include "migration/colo.h"
226
227
#ifndef ETH_P_RARP
228
#define ETH_P_RARP 0x8035
229
@@ -XXX,XX +XXX,XX @@ enum qemu_vm_cmd {
230
were previously sent during
231
precopy but are dirty. */
232
MIG_CMD_PACKAGED, /* Send a wrapped stream within this stream */
233
+ MIG_CMD_ENABLE_COLO, /* Enable COLO */
234
MIG_CMD_POSTCOPY_RESUME, /* resume postcopy on dest */
235
MIG_CMD_RECV_BITMAP, /* Request for recved bitmap on dst */
236
MIG_CMD_MAX
237
@@ -XXX,XX +XXX,XX @@ static void qemu_savevm_command_send(QEMUFile *f,
238
qemu_fflush(f);
239
}
129
}
240
241
+void qemu_savevm_send_colo_enable(QEMUFile *f)
242
+{
243
+ trace_savevm_send_colo_enable();
244
+ qemu_savevm_command_send(f, MIG_CMD_ENABLE_COLO, 0, NULL);
245
+}
246
+
247
void qemu_savevm_send_ping(QEMUFile *f, uint32_t value)
248
{
249
uint32_t buf;
250
@@ -XXX,XX +XXX,XX @@ static int loadvm_handle_recv_bitmap(MigrationIncomingState *mis,
251
return 0;
252
}
253
254
+static int loadvm_process_enable_colo(MigrationIncomingState *mis)
255
+{
256
+ migration_incoming_enable_colo();
257
+ return 0;
258
+}
259
+
260
/*
261
* Process an incoming 'QEMU_VM_COMMAND'
262
* 0 just a normal return
263
@@ -XXX,XX +XXX,XX @@ static int loadvm_process_command(QEMUFile *f)
264
265
case MIG_CMD_RECV_BITMAP:
266
return loadvm_handle_recv_bitmap(mis, len);
267
+
268
+ case MIG_CMD_ENABLE_COLO:
269
+ return loadvm_process_enable_colo(mis);
270
}
271
272
return 0;
273
diff --git a/migration/savevm.h b/migration/savevm.h
274
index XXXXXXX..XXXXXXX 100644
275
--- a/migration/savevm.h
276
+++ b/migration/savevm.h
277
@@ -XXX,XX +XXX,XX @@ void qemu_savevm_send_postcopy_ram_discard(QEMUFile *f, const char *name,
278
uint16_t len,
279
uint64_t *start_list,
280
uint64_t *length_list);
281
+void qemu_savevm_send_colo_enable(QEMUFile *f);
282
283
int qemu_loadvm_state(QEMUFile *f);
284
void qemu_loadvm_state_cleanup(void);
285
diff --git a/migration/trace-events b/migration/trace-events
286
index XXXXXXX..XXXXXXX 100644
287
--- a/migration/trace-events
288
+++ b/migration/trace-events
289
@@ -XXX,XX +XXX,XX @@ savevm_send_ping(uint32_t val) "0x%x"
290
savevm_send_postcopy_listen(void) ""
291
savevm_send_postcopy_run(void) ""
292
savevm_send_postcopy_resume(void) ""
293
+savevm_send_colo_enable(void) ""
294
savevm_send_recv_bitmap(char *name) "%s"
295
savevm_state_setup(void) ""
296
savevm_state_resume_prepare(void) ""
297
diff --git a/vl.c b/vl.c
298
index XXXXXXX..XXXXXXX 100644
299
--- a/vl.c
300
+++ b/vl.c
301
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp)
302
#endif
303
}
304
305
- colo_info_init();
306
-
307
if (net_init_clients(&err) < 0) {
308
error_report_err(err);
309
exit(1);
310
--
130
--
311
2.5.0
131
2.7.4
312
132
313
133
diff view generated by jsdifflib
Deleted patch
1
From: Zhang Chen <zhangckid@gmail.com>
2
1
3
We record the address of the dirty pages that received,
4
it will help flushing pages that cached into SVM.
5
6
Here, it is a trick, we record dirty pages by re-using migration
7
dirty bitmap. In the later patch, we will start the dirty log
8
for SVM, just like migration, in this way, we can record both
9
the dirty pages caused by PVM and SVM, we only flush those dirty
10
pages from RAM cache while do checkpoint.
11
12
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
13
Signed-off-by: Zhang Chen <zhangckid@gmail.com>
14
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
15
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
16
Signed-off-by: Jason Wang <jasowang@redhat.com>
17
---
18
migration/ram.c | 43 ++++++++++++++++++++++++++++++++++++++++---
19
1 file changed, 40 insertions(+), 3 deletions(-)
20
21
diff --git a/migration/ram.c b/migration/ram.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/migration/ram.c
24
+++ b/migration/ram.c
25
@@ -XXX,XX +XXX,XX @@ static inline void *colo_cache_from_block_offset(RAMBlock *block,
26
__func__, block->idstr);
27
return NULL;
28
}
29
+
30
+ /*
31
+ * During colo checkpoint, we need bitmap of these migrated pages.
32
+ * It help us to decide which pages in ram cache should be flushed
33
+ * into VM's RAM later.
34
+ */
35
+ if (!test_and_set_bit(offset >> TARGET_PAGE_BITS, block->bmap)) {
36
+ ram_state->migration_dirty_pages++;
37
+ }
38
return block->colo_cache + offset;
39
}
40
41
@@ -XXX,XX +XXX,XX @@ int colo_init_ram_cache(void)
42
RAMBlock *block;
43
44
rcu_read_lock();
45
- QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
46
+ RAMBLOCK_FOREACH_MIGRATABLE(block) {
47
block->colo_cache = qemu_anon_ram_alloc(block->used_length,
48
NULL,
49
false);
50
@@ -XXX,XX +XXX,XX @@ int colo_init_ram_cache(void)
51
memcpy(block->colo_cache, block->host, block->used_length);
52
}
53
rcu_read_unlock();
54
+ /*
55
+ * Record the dirty pages that sent by PVM, we use this dirty bitmap together
56
+ * with to decide which page in cache should be flushed into SVM's RAM. Here
57
+ * we use the same name 'ram_bitmap' as for migration.
58
+ */
59
+ if (ram_bytes_total()) {
60
+ RAMBlock *block;
61
+
62
+ RAMBLOCK_FOREACH_MIGRATABLE(block) {
63
+ unsigned long pages = block->max_length >> TARGET_PAGE_BITS;
64
+
65
+ block->bmap = bitmap_new(pages);
66
+ bitmap_set(block->bmap, 0, pages);
67
+ }
68
+ }
69
+ ram_state = g_new0(RAMState, 1);
70
+ ram_state->migration_dirty_pages = 0;
71
+
72
return 0;
73
74
out_locked:
75
- QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
76
+
77
+ RAMBLOCK_FOREACH_MIGRATABLE(block) {
78
if (block->colo_cache) {
79
qemu_anon_ram_free(block->colo_cache, block->used_length);
80
block->colo_cache = NULL;
81
@@ -XXX,XX +XXX,XX @@ void colo_release_ram_cache(void)
82
{
83
RAMBlock *block;
84
85
+ RAMBLOCK_FOREACH_MIGRATABLE(block) {
86
+ g_free(block->bmap);
87
+ block->bmap = NULL;
88
+ }
89
+
90
rcu_read_lock();
91
- QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
92
+
93
+ RAMBLOCK_FOREACH_MIGRATABLE(block) {
94
if (block->colo_cache) {
95
qemu_anon_ram_free(block->colo_cache, block->used_length);
96
block->colo_cache = NULL;
97
}
98
}
99
+
100
rcu_read_unlock();
101
+ g_free(ram_state);
102
+ ram_state = NULL;
103
}
104
105
/**
106
--
107
2.5.0
108
109
diff view generated by jsdifflib
Deleted patch
1
From: Zhang Chen <zhangckid@gmail.com>
2
1
3
During the time of VM's running, PVM may dirty some pages, we will transfer
4
PVM's dirty pages to SVM and store them into SVM's RAM cache at next checkpoint
5
time. So, the content of SVM's RAM cache will always be same with PVM's memory
6
after checkpoint.
7
8
Instead of flushing all content of PVM's RAM cache into SVM's MEMORY,
9
we do this in a more efficient way:
10
Only flush any page that dirtied by PVM since last checkpoint.
11
In this way, we can ensure SVM's memory same with PVM's.
12
13
Besides, we must ensure flush RAM cache before load device state.
14
15
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
16
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
17
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
18
Signed-off-by: Jason Wang <jasowang@redhat.com>
19
---
20
migration/ram.c | 37 +++++++++++++++++++++++++++++++++++++
21
migration/trace-events | 2 ++
22
2 files changed, 39 insertions(+)
23
24
diff --git a/migration/ram.c b/migration/ram.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/migration/ram.c
27
+++ b/migration/ram.c
28
@@ -XXX,XX +XXX,XX @@ static bool postcopy_is_running(void)
29
return ps >= POSTCOPY_INCOMING_LISTENING && ps < POSTCOPY_INCOMING_END;
30
}
31
32
+/*
33
+ * Flush content of RAM cache into SVM's memory.
34
+ * Only flush the pages that be dirtied by PVM or SVM or both.
35
+ */
36
+static void colo_flush_ram_cache(void)
37
+{
38
+ RAMBlock *block = NULL;
39
+ void *dst_host;
40
+ void *src_host;
41
+ unsigned long offset = 0;
42
+
43
+ trace_colo_flush_ram_cache_begin(ram_state->migration_dirty_pages);
44
+ rcu_read_lock();
45
+ block = QLIST_FIRST_RCU(&ram_list.blocks);
46
+
47
+ while (block) {
48
+ offset = migration_bitmap_find_dirty(ram_state, block, offset);
49
+
50
+ if (offset << TARGET_PAGE_BITS >= block->used_length) {
51
+ offset = 0;
52
+ block = QLIST_NEXT_RCU(block, next);
53
+ } else {
54
+ migration_bitmap_clear_dirty(ram_state, block, offset);
55
+ dst_host = block->host + (offset << TARGET_PAGE_BITS);
56
+ src_host = block->colo_cache + (offset << TARGET_PAGE_BITS);
57
+ memcpy(dst_host, src_host, TARGET_PAGE_SIZE);
58
+ }
59
+ }
60
+
61
+ rcu_read_unlock();
62
+ trace_colo_flush_ram_cache_end();
63
+}
64
+
65
static int ram_load(QEMUFile *f, void *opaque, int version_id)
66
{
67
int flags = 0, ret = 0, invalid_flags = 0;
68
@@ -XXX,XX +XXX,XX @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
69
ret |= wait_for_decompress_done();
70
rcu_read_unlock();
71
trace_ram_load_complete(ret, seq_iter);
72
+
73
+ if (!ret && migration_incoming_in_colo_state()) {
74
+ colo_flush_ram_cache();
75
+ }
76
return ret;
77
}
78
79
diff --git a/migration/trace-events b/migration/trace-events
80
index XXXXXXX..XXXXXXX 100644
81
--- a/migration/trace-events
82
+++ b/migration/trace-events
83
@@ -XXX,XX +XXX,XX @@ ram_dirty_bitmap_sync_start(void) ""
84
ram_dirty_bitmap_sync_wait(void) ""
85
ram_dirty_bitmap_sync_complete(void) ""
86
ram_state_resume_prepare(uint64_t v) "%" PRId64
87
+colo_flush_ram_cache_begin(uint64_t dirty_pages) "dirty_pages %" PRIu64
88
+colo_flush_ram_cache_end(void) ""
89
90
# migration/migration.c
91
await_return_path_close_on_source_close(void) ""
92
--
93
2.5.0
94
95
diff view generated by jsdifflib
Deleted patch
1
From: zhanghailiang <zhang.zhanghailiang@huawei.com>
2
1
3
If some errors happen during VM's COLO FT stage, it's important to
4
notify the users of this event. Together with 'x-colo-lost-heartbeat',
5
Users can intervene in COLO's failover work immediately.
6
If users don't want to get involved in COLO's failover verdict,
7
it is still necessary to notify users that we exited COLO mode.
8
9
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
10
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
11
Signed-off-by: Zhang Chen <zhangckid@gmail.com>
12
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
13
Signed-off-by: Jason Wang <jasowang@redhat.com>
14
---
15
migration/colo.c | 31 +++++++++++++++++++++++++++++++
16
qapi/migration.json | 38 ++++++++++++++++++++++++++++++++++++++
17
2 files changed, 69 insertions(+)
18
19
diff --git a/migration/colo.c b/migration/colo.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/migration/colo.c
22
+++ b/migration/colo.c
23
@@ -XXX,XX +XXX,XX @@
24
#include "net/colo-compare.h"
25
#include "net/colo.h"
26
#include "block/block.h"
27
+#include "qapi/qapi-events-migration.h"
28
29
static bool vmstate_loading;
30
static Notifier packets_compare_notifier;
31
@@ -XXX,XX +XXX,XX @@ out:
32
qemu_fclose(fb);
33
}
34
35
+ /*
36
+ * There are only two reasons we can get here, some error happened
37
+ * or the user triggered failover.
38
+ */
39
+ switch (failover_get_state()) {
40
+ case FAILOVER_STATUS_NONE:
41
+ qapi_event_send_colo_exit(COLO_MODE_PRIMARY,
42
+ COLO_EXIT_REASON_ERROR);
43
+ break;
44
+ case FAILOVER_STATUS_REQUIRE:
45
+ qapi_event_send_colo_exit(COLO_MODE_PRIMARY,
46
+ COLO_EXIT_REASON_REQUEST);
47
+ break;
48
+ default:
49
+ abort();
50
+ }
51
+
52
/* Hope this not to be too long to wait here */
53
qemu_sem_wait(&s->colo_exit_sem);
54
qemu_sem_destroy(&s->colo_exit_sem);
55
@@ -XXX,XX +XXX,XX @@ out:
56
error_report_err(local_err);
57
}
58
59
+ switch (failover_get_state()) {
60
+ case FAILOVER_STATUS_NONE:
61
+ qapi_event_send_colo_exit(COLO_MODE_SECONDARY,
62
+ COLO_EXIT_REASON_ERROR);
63
+ break;
64
+ case FAILOVER_STATUS_REQUIRE:
65
+ qapi_event_send_colo_exit(COLO_MODE_SECONDARY,
66
+ COLO_EXIT_REASON_REQUEST);
67
+ break;
68
+ default:
69
+ abort();
70
+ }
71
+
72
if (fb) {
73
qemu_fclose(fb);
74
}
75
diff --git a/qapi/migration.json b/qapi/migration.json
76
index XXXXXXX..XXXXXXX 100644
77
--- a/qapi/migration.json
78
+++ b/qapi/migration.json
79
@@ -XXX,XX +XXX,XX @@
80
'data': [ 'none', 'require', 'active', 'completed', 'relaunch' ] }
81
82
##
83
+# @COLO_EXIT:
84
+#
85
+# Emitted when VM finishes COLO mode due to some errors happening or
86
+# at the request of users.
87
+#
88
+# @mode: report COLO mode when COLO exited.
89
+#
90
+# @reason: describes the reason for the COLO exit.
91
+#
92
+# Since: 3.1
93
+#
94
+# Example:
95
+#
96
+# <- { "timestamp": {"seconds": 2032141960, "microseconds": 417172},
97
+# "event": "COLO_EXIT", "data": {"mode": "primary", "reason": "request" } }
98
+#
99
+##
100
+{ 'event': 'COLO_EXIT',
101
+ 'data': {'mode': 'COLOMode', 'reason': 'COLOExitReason' } }
102
+
103
+##
104
+# @COLOExitReason:
105
+#
106
+# The reason for a COLO exit
107
+#
108
+# @none: no failover has ever happened. This can't occur in the
109
+# COLO_EXIT event, only in the result of query-colo-status.
110
+#
111
+# @request: COLO exit is due to an external request
112
+#
113
+# @error: COLO exit is due to an internal error
114
+#
115
+# Since: 3.1
116
+##
117
+{ 'enum': 'COLOExitReason',
118
+ 'data': [ 'none', 'request', 'error' ] }
119
+
120
+##
121
# @x-colo-lost-heartbeat:
122
#
123
# Tell qemu that heartbeat is lost, request it to do takeover procedures.
124
--
125
2.5.0
126
127
diff view generated by jsdifflib
Deleted patch
1
From: Zhang Chen <chen.zhang@intel.com>
2
1
3
Suggested by Markus Armbruster rename COLO unknown mode to none mode.
4
5
Signed-off-by: Zhang Chen <zhangckid@gmail.com>
6
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Markus Armbruster <armbru@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
11
migration/colo-failover.c | 2 +-
12
migration/colo.c | 2 +-
13
qapi/migration.json | 10 +++++-----
14
3 files changed, 7 insertions(+), 7 deletions(-)
15
16
diff --git a/migration/colo-failover.c b/migration/colo-failover.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/migration/colo-failover.c
19
+++ b/migration/colo-failover.c
20
@@ -XXX,XX +XXX,XX @@ FailoverStatus failover_get_state(void)
21
22
void qmp_x_colo_lost_heartbeat(Error **errp)
23
{
24
- if (get_colo_mode() == COLO_MODE_UNKNOWN) {
25
+ if (get_colo_mode() == COLO_MODE_NONE) {
26
error_setg(errp, QERR_FEATURE_DISABLED, "colo");
27
return;
28
}
29
diff --git a/migration/colo.c b/migration/colo.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/migration/colo.c
32
+++ b/migration/colo.c
33
@@ -XXX,XX +XXX,XX @@ COLOMode get_colo_mode(void)
34
} else if (migration_incoming_in_colo_state()) {
35
return COLO_MODE_SECONDARY;
36
} else {
37
- return COLO_MODE_UNKNOWN;
38
+ return COLO_MODE_NONE;
39
}
40
}
41
42
diff --git a/qapi/migration.json b/qapi/migration.json
43
index XXXXXXX..XXXXXXX 100644
44
--- a/qapi/migration.json
45
+++ b/qapi/migration.json
46
@@ -XXX,XX +XXX,XX @@
47
##
48
# @COLOMode:
49
#
50
-# The colo mode
51
+# The COLO current mode.
52
#
53
-# @unknown: unknown mode
54
+# @none: COLO is disabled.
55
#
56
-# @primary: master side
57
+# @primary: COLO node in primary side.
58
#
59
-# @secondary: slave side
60
+# @secondary: COLO node in slave side.
61
#
62
# Since: 2.8
63
##
64
{ 'enum': 'COLOMode',
65
- 'data': [ 'unknown', 'primary', 'secondary'] }
66
+ 'data': [ 'none', 'primary', 'secondary'] }
67
68
##
69
# @FailoverStatus:
70
--
71
2.5.0
72
73
diff view generated by jsdifflib
Deleted patch
1
From: Zhang Chen <zhangckid@gmail.com>
2
1
3
Libvirt or other high level software can use this command query colo status.
4
You can test this command like that:
5
{'execute':'query-colo-status'}
6
7
Signed-off-by: Zhang Chen <zhangckid@gmail.com>
8
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
11
migration/colo.c | 21 +++++++++++++++++++++
12
qapi/migration.json | 32 ++++++++++++++++++++++++++++++++
13
2 files changed, 53 insertions(+)
14
15
diff --git a/migration/colo.c b/migration/colo.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/migration/colo.c
18
+++ b/migration/colo.c
19
@@ -XXX,XX +XXX,XX @@
20
#include "net/colo.h"
21
#include "block/block.h"
22
#include "qapi/qapi-events-migration.h"
23
+#include "qapi/qmp/qerror.h"
24
25
static bool vmstate_loading;
26
static Notifier packets_compare_notifier;
27
@@ -XXX,XX +XXX,XX @@ void qmp_xen_colo_do_checkpoint(Error **errp)
28
#endif
29
}
30
31
+COLOStatus *qmp_query_colo_status(Error **errp)
32
+{
33
+ COLOStatus *s = g_new0(COLOStatus, 1);
34
+
35
+ s->mode = get_colo_mode();
36
+
37
+ switch (failover_get_state()) {
38
+ case FAILOVER_STATUS_NONE:
39
+ s->reason = COLO_EXIT_REASON_NONE;
40
+ break;
41
+ case FAILOVER_STATUS_REQUIRE:
42
+ s->reason = COLO_EXIT_REASON_REQUEST;
43
+ break;
44
+ default:
45
+ s->reason = COLO_EXIT_REASON_ERROR;
46
+ }
47
+
48
+ return s;
49
+}
50
+
51
static void colo_send_message(QEMUFile *f, COLOMessage msg,
52
Error **errp)
53
{
54
diff --git a/qapi/migration.json b/qapi/migration.json
55
index XXXXXXX..XXXXXXX 100644
56
--- a/qapi/migration.json
57
+++ b/qapi/migration.json
58
@@ -XXX,XX +XXX,XX @@
59
{ 'command': 'xen-colo-do-checkpoint' }
60
61
##
62
+# @COLOStatus:
63
+#
64
+# The result format for 'query-colo-status'.
65
+#
66
+# @mode: COLO running mode. If COLO is running, this field will return
67
+# 'primary' or 'secondary'.
68
+#
69
+# @reason: describes the reason for the COLO exit.
70
+#
71
+# Since: 3.0
72
+##
73
+{ 'struct': 'COLOStatus',
74
+ 'data': { 'mode': 'COLOMode', 'reason': 'COLOExitReason' } }
75
+
76
+##
77
+# @query-colo-status:
78
+#
79
+# Query COLO status while the vm is running.
80
+#
81
+# Returns: A @COLOStatus object showing the status.
82
+#
83
+# Example:
84
+#
85
+# -> { "execute": "query-colo-status" }
86
+# <- { "return": { "mode": "primary", "active": true, "reason": "request" } }
87
+#
88
+# Since: 3.0
89
+##
90
+{ 'command': 'query-colo-status',
91
+ 'returns': 'COLOStatus' }
92
+
93
+##
94
# @migrate-recover:
95
#
96
# Provide a recovery migration stream URI.
97
--
98
2.5.0
99
100
diff view generated by jsdifflib
Deleted patch
1
From: Zhang Chen <zhangckid@gmail.com>
2
1
3
There are several stages during loadvm/savevm process. In different stage,
4
migration incoming processes different types of sections.
5
We want to control these stages more accuracy, it will benefit COLO
6
performance, we don't have to save type of QEMU_VM_SECTION_START
7
sections everytime while do checkpoint, besides, we want to separate
8
the process of saving/loading memory and devices state.
9
10
So we add three new helper functions: qemu_load_device_state() and
11
qemu_savevm_live_state() to achieve different process during migration.
12
13
Besides, we make qemu_loadvm_state_main() and qemu_save_device_state()
14
public, and simplify the codes of qemu_save_device_state() by calling the
15
wrapper qemu_savevm_state_header().
16
17
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
18
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
19
Signed-off-by: Zhang Chen <zhangckid@gmail.com>
20
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
21
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
22
Signed-off-by: Jason Wang <jasowang@redhat.com>
23
---
24
migration/colo.c | 41 ++++++++++++++++++++++++++++++++---------
25
migration/savevm.c | 36 +++++++++++++++++++++++++++++-------
26
migration/savevm.h | 4 ++++
27
3 files changed, 65 insertions(+), 16 deletions(-)
28
29
diff --git a/migration/colo.c b/migration/colo.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/migration/colo.c
32
+++ b/migration/colo.c
33
@@ -XXX,XX +XXX,XX @@
34
#include "block/block.h"
35
#include "qapi/qapi-events-migration.h"
36
#include "qapi/qmp/qerror.h"
37
+#include "sysemu/cpus.h"
38
39
static bool vmstate_loading;
40
static Notifier packets_compare_notifier;
41
@@ -XXX,XX +XXX,XX @@ static int colo_do_checkpoint_transaction(MigrationState *s,
42
43
/* Disable block migration */
44
migrate_set_block_enabled(false, &local_err);
45
- qemu_savevm_state_header(fb);
46
- qemu_savevm_state_setup(fb);
47
qemu_mutex_lock_iothread();
48
replication_do_checkpoint_all(&local_err);
49
if (local_err) {
50
qemu_mutex_unlock_iothread();
51
goto out;
52
}
53
- qemu_savevm_state_complete_precopy(fb, false, false);
54
- qemu_mutex_unlock_iothread();
55
-
56
- qemu_fflush(fb);
57
58
colo_send_message(s->to_dst_file, COLO_MESSAGE_VMSTATE_SEND, &local_err);
59
if (local_err) {
60
+ qemu_mutex_unlock_iothread();
61
+ goto out;
62
+ }
63
+ /* Note: device state is saved into buffer */
64
+ ret = qemu_save_device_state(fb);
65
+
66
+ qemu_mutex_unlock_iothread();
67
+ if (ret < 0) {
68
goto out;
69
}
70
/*
71
+ * Only save VM's live state, which not including device state.
72
+ * TODO: We may need a timeout mechanism to prevent COLO process
73
+ * to be blocked here.
74
+ */
75
+ qemu_savevm_live_state(s->to_dst_file);
76
+
77
+ qemu_fflush(fb);
78
+
79
+ /*
80
* We need the size of the VMstate data in Secondary side,
81
* With which we can decide how much data should be read.
82
*/
83
@@ -XXX,XX +XXX,XX @@ void *colo_process_incoming_thread(void *opaque)
84
uint64_t total_size;
85
uint64_t value;
86
Error *local_err = NULL;
87
+ int ret;
88
89
rcu_register_thread();
90
qemu_sem_init(&mis->colo_incoming_sem, 0);
91
@@ -XXX,XX +XXX,XX @@ void *colo_process_incoming_thread(void *opaque)
92
goto out;
93
}
94
95
+ qemu_mutex_lock_iothread();
96
+ cpu_synchronize_all_pre_loadvm();
97
+ ret = qemu_loadvm_state_main(mis->from_src_file, mis);
98
+ qemu_mutex_unlock_iothread();
99
+
100
+ if (ret < 0) {
101
+ error_report("Load VM's live state (ram) error");
102
+ goto out;
103
+ }
104
+
105
value = colo_receive_message_value(mis->from_src_file,
106
COLO_MESSAGE_VMSTATE_SIZE, &local_err);
107
if (local_err) {
108
@@ -XXX,XX +XXX,XX @@ void *colo_process_incoming_thread(void *opaque)
109
}
110
111
qemu_mutex_lock_iothread();
112
- qemu_system_reset(SHUTDOWN_CAUSE_NONE);
113
vmstate_loading = true;
114
- if (qemu_loadvm_state(fb) < 0) {
115
- error_report("COLO: loadvm failed");
116
+ ret = qemu_load_device_state(fb);
117
+ if (ret < 0) {
118
+ error_report("COLO: load device state failed");
119
qemu_mutex_unlock_iothread();
120
goto out;
121
}
122
diff --git a/migration/savevm.c b/migration/savevm.c
123
index XXXXXXX..XXXXXXX 100644
124
--- a/migration/savevm.c
125
+++ b/migration/savevm.c
126
@@ -XXX,XX +XXX,XX @@ done:
127
return ret;
128
}
129
130
-static int qemu_save_device_state(QEMUFile *f)
131
+void qemu_savevm_live_state(QEMUFile *f)
132
{
133
- SaveStateEntry *se;
134
+ /* save QEMU_VM_SECTION_END section */
135
+ qemu_savevm_state_complete_precopy(f, true, false);
136
+ qemu_put_byte(f, QEMU_VM_EOF);
137
+}
138
139
- qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
140
- qemu_put_be32(f, QEMU_VM_FILE_VERSION);
141
+int qemu_save_device_state(QEMUFile *f)
142
+{
143
+ SaveStateEntry *se;
144
145
+ if (!migration_in_colo_state()) {
146
+ qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
147
+ qemu_put_be32(f, QEMU_VM_FILE_VERSION);
148
+ }
149
cpu_synchronize_all_states();
150
151
QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
152
@@ -XXX,XX +XXX,XX @@ enum LoadVMExitCodes {
153
LOADVM_QUIT = 1,
154
};
155
156
-static int qemu_loadvm_state_main(QEMUFile *f, MigrationIncomingState *mis);
157
-
158
/* ------ incoming postcopy messages ------ */
159
/* 'advise' arrives before any transfers just to tell us that a postcopy
160
* *might* happen - it might be skipped if precopy transferred everything
161
@@ -XXX,XX +XXX,XX @@ static bool postcopy_pause_incoming(MigrationIncomingState *mis)
162
return true;
163
}
164
165
-static int qemu_loadvm_state_main(QEMUFile *f, MigrationIncomingState *mis)
166
+int qemu_loadvm_state_main(QEMUFile *f, MigrationIncomingState *mis)
167
{
168
uint8_t section_type;
169
int ret = 0;
170
@@ -XXX,XX +XXX,XX @@ int qemu_loadvm_state(QEMUFile *f)
171
return ret;
172
}
173
174
+int qemu_load_device_state(QEMUFile *f)
175
+{
176
+ MigrationIncomingState *mis = migration_incoming_get_current();
177
+ int ret;
178
+
179
+ /* Load QEMU_VM_SECTION_FULL section */
180
+ ret = qemu_loadvm_state_main(f, mis);
181
+ if (ret < 0) {
182
+ error_report("Failed to load device state: %d", ret);
183
+ return ret;
184
+ }
185
+
186
+ cpu_synchronize_all_post_init();
187
+ return 0;
188
+}
189
+
190
int save_snapshot(const char *name, Error **errp)
191
{
192
BlockDriverState *bs, *bs1;
193
diff --git a/migration/savevm.h b/migration/savevm.h
194
index XXXXXXX..XXXXXXX 100644
195
--- a/migration/savevm.h
196
+++ b/migration/savevm.h
197
@@ -XXX,XX +XXX,XX @@ void qemu_savevm_send_postcopy_ram_discard(QEMUFile *f, const char *name,
198
uint64_t *start_list,
199
uint64_t *length_list);
200
void qemu_savevm_send_colo_enable(QEMUFile *f);
201
+void qemu_savevm_live_state(QEMUFile *f);
202
+int qemu_save_device_state(QEMUFile *f);
203
204
int qemu_loadvm_state(QEMUFile *f);
205
void qemu_loadvm_state_cleanup(void);
206
+int qemu_loadvm_state_main(QEMUFile *f, MigrationIncomingState *mis);
207
+int qemu_load_device_state(QEMUFile *f);
208
209
#endif
210
--
211
2.5.0
212
213
diff view generated by jsdifflib
Deleted patch
1
From: zhanghailiang <zhang.zhanghailiang@huawei.com>
2
1
3
Don't need to flush all VM's ram from cache, only
4
flush the dirty pages since last checkpoint
5
6
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
7
Signed-off-by: Zhang Chen <zhangckid@gmail.com>
8
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
9
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
10
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
13
migration/ram.c | 9 +++++++++
14
1 file changed, 9 insertions(+)
15
16
diff --git a/migration/ram.c b/migration/ram.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/migration/ram.c
19
+++ b/migration/ram.c
20
@@ -XXX,XX +XXX,XX @@ int colo_init_ram_cache(void)
21
}
22
ram_state = g_new0(RAMState, 1);
23
ram_state->migration_dirty_pages = 0;
24
+ memory_global_dirty_log_start();
25
26
return 0;
27
28
@@ -XXX,XX +XXX,XX @@ void colo_release_ram_cache(void)
29
{
30
RAMBlock *block;
31
32
+ memory_global_dirty_log_stop();
33
RAMBLOCK_FOREACH_MIGRATABLE(block) {
34
g_free(block->bmap);
35
block->bmap = NULL;
36
@@ -XXX,XX +XXX,XX @@ static void colo_flush_ram_cache(void)
37
void *src_host;
38
unsigned long offset = 0;
39
40
+ memory_global_dirty_log_sync();
41
+ rcu_read_lock();
42
+ RAMBLOCK_FOREACH_MIGRATABLE(block) {
43
+ migration_bitmap_sync_range(ram_state, block, 0, block->used_length);
44
+ }
45
+ rcu_read_unlock();
46
+
47
trace_colo_flush_ram_cache_begin(ram_state->migration_dirty_pages);
48
rcu_read_lock();
49
block = QLIST_FIRST_RCU(&ram_list.blocks);
50
--
51
2.5.0
52
53
diff view generated by jsdifflib
Deleted patch
1
From: zhanghailiang <zhang.zhanghailiang@huawei.com>
2
1
3
Notify all net filters about the checkpoint and failover event.
4
5
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
6
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
9
migration/colo.c | 15 +++++++++++++++
10
1 file changed, 15 insertions(+)
11
12
diff --git a/migration/colo.c b/migration/colo.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/migration/colo.c
15
+++ b/migration/colo.c
16
@@ -XXX,XX +XXX,XX @@
17
#include "qapi/qapi-events-migration.h"
18
#include "qapi/qmp/qerror.h"
19
#include "sysemu/cpus.h"
20
+#include "net/filter.h"
21
22
static bool vmstate_loading;
23
static Notifier packets_compare_notifier;
24
@@ -XXX,XX +XXX,XX @@ static void secondary_vm_do_failover(void)
25
error_report_err(local_err);
26
}
27
28
+ /* Notify all filters of all NIC to do checkpoint */
29
+ colo_notify_filters_event(COLO_EVENT_FAILOVER, &local_err);
30
+ if (local_err) {
31
+ error_report_err(local_err);
32
+ }
33
+
34
if (!autostart) {
35
error_report("\"-S\" qemu option will be ignored in secondary side");
36
/* recover runstate to normal migration finish state */
37
@@ -XXX,XX +XXX,XX @@ void *colo_process_incoming_thread(void *opaque)
38
goto out;
39
}
40
41
+ /* Notify all filters of all NIC to do checkpoint */
42
+ colo_notify_filters_event(COLO_EVENT_CHECKPOINT, &local_err);
43
+
44
+ if (local_err) {
45
+ qemu_mutex_unlock_iothread();
46
+ goto out;
47
+ }
48
+
49
vmstate_loading = false;
50
vm_start();
51
trace_colo_vm_state_change("stop", "run");
52
--
53
2.5.0
54
55
diff view generated by jsdifflib
Deleted patch
1
From: zhanghailiang <zhang.zhanghailiang@huawei.com>
2
1
3
COLO thread may sleep at qemu_sem_wait(&s->colo_checkpoint_sem),
4
while failover works begin, It's better to wakeup it to quick
5
the process.
6
7
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
8
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
11
migration/colo.c | 8 ++++++++
12
1 file changed, 8 insertions(+)
13
14
diff --git a/migration/colo.c b/migration/colo.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/migration/colo.c
17
+++ b/migration/colo.c
18
@@ -XXX,XX +XXX,XX @@ static void primary_vm_do_failover(void)
19
20
migrate_set_state(&s->state, MIGRATION_STATUS_COLO,
21
MIGRATION_STATUS_COMPLETED);
22
+ /*
23
+ * kick COLO thread which might wait at
24
+ * qemu_sem_wait(&s->colo_checkpoint_sem).
25
+ */
26
+ colo_checkpoint_notify(migrate_get_current());
27
28
/*
29
* Wake up COLO thread which may blocked in recv() or send(),
30
@@ -XXX,XX +XXX,XX @@ static void colo_process_checkpoint(MigrationState *s)
31
32
qemu_sem_wait(&s->colo_checkpoint_sem);
33
34
+ if (s->state != MIGRATION_STATUS_COLO) {
35
+ goto out;
36
+ }
37
ret = colo_do_checkpoint_transaction(s, bioc, fb);
38
if (ret < 0) {
39
goto out;
40
--
41
2.5.0
42
43
diff view generated by jsdifflib
Deleted patch
1
From: Zhang Chen <chen.zhang@intel.com>
2
1
3
This diagram make user better understand COLO.
4
Suggested by Markus Armbruster.
5
6
Signed-off-by: Zhang Chen <zhangckid@gmail.com>
7
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
10
docs/COLO-FT.txt | 34 ++++++++++++++++++++++++++++++++++
11
1 file changed, 34 insertions(+)
12
13
diff --git a/docs/COLO-FT.txt b/docs/COLO-FT.txt
14
index XXXXXXX..XXXXXXX 100644
15
--- a/docs/COLO-FT.txt
16
+++ b/docs/COLO-FT.txt
17
@@ -XXX,XX +XXX,XX @@ Note:
18
HeartBeat has not been implemented yet, so you need to trigger failover process
19
by using 'x-colo-lost-heartbeat' command.
20
21
+== COLO operation status ==
22
+
23
++-----------------+
24
+| |
25
+| Start COLO |
26
+| |
27
++--------+--------+
28
+ |
29
+ | Main qmp command:
30
+ | migrate-set-capabilities with x-colo
31
+ | migrate
32
+ |
33
+ v
34
++--------+--------+
35
+| |
36
+| COLO running |
37
+| |
38
++--------+--------+
39
+ |
40
+ | Main qmp command:
41
+ | x-colo-lost-heartbeat
42
+ | or
43
+ | some error happened
44
+ v
45
++--------+--------+
46
+| | send qmp event:
47
+| COLO failover | COLO_EXIT
48
+| |
49
++-----------------+
50
+
51
+COLO use the qmp command to switch and report operation status.
52
+The diagram just shows the main qmp command, you can get the detail
53
+in test procedure.
54
+
55
== Test procedure ==
56
1. Startup qemu
57
Primary:
58
--
59
2.5.0
60
61
diff view generated by jsdifflib
Deleted patch
1
From: liujunjie <liujunjie23@huawei.com>
2
1
3
Before, we did not clear callback like handle_output when delete
4
the virtqueue which may result be segmentfault.
5
The scene is as follows:
6
1. Start a vm with multiqueue vhost-net,
7
2. then we write VIRTIO_PCI_GUEST_FEATURES in PCI configuration to
8
triger multiqueue disable in this vm which will delete the virtqueue.
9
In this step, the tx_bh is deleted but the callback virtio_net_handle_tx_bh
10
still exist.
11
3. Finally, we write VIRTIO_PCI_QUEUE_NOTIFY in PCI configuration to
12
notify the deleted virtqueue. In this way, virtio_net_handle_tx_bh
13
will be called and qemu will be crashed.
14
15
Although the way described above is uncommon, we had better reinforce it.
16
17
CC: qemu-stable@nongnu.org
18
Signed-off-by: liujunjie <liujunjie23@huawei.com>
19
Signed-off-by: Jason Wang <jasowang@redhat.com>
20
---
21
hw/virtio/virtio.c | 2 ++
22
1 file changed, 2 insertions(+)
23
24
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/virtio/virtio.c
27
+++ b/hw/virtio/virtio.c
28
@@ -XXX,XX +XXX,XX @@ void virtio_del_queue(VirtIODevice *vdev, int n)
29
30
vdev->vq[n].vring.num = 0;
31
vdev->vq[n].vring.num_default = 0;
32
+ vdev->vq[n].handle_output = NULL;
33
+ vdev->vq[n].handle_aio_output = NULL;
34
}
35
36
static void virtio_set_isr(VirtIODevice *vdev, int value)
37
--
38
2.5.0
39
40
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
2
2
3
When using the "-device" option, the property is called "mac".
3
Signed-off-by: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
4
"macaddr" is only used for the legacy "-net nic" option.
5
6
Reported-by: Harald Hoyer <harald@redhat.com>
7
Reviewed-by: Markus Armbruster <armbru@redhat.com>
8
Signed-off-by: Thomas Huth <thuth@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
4
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
5
---
11
qemu-options.hx | 2 +-
6
qemu-options.hx | 25 +++++++++++++++++++++++++
12
1 file changed, 1 insertion(+), 1 deletion(-)
7
1 file changed, 25 insertions(+)
13
8
14
diff --git a/qemu-options.hx b/qemu-options.hx
9
diff --git a/qemu-options.hx b/qemu-options.hx
15
index XXXXXXX..XXXXXXX 100644
10
index XXXXXXX..XXXXXXX 100644
16
--- a/qemu-options.hx
11
--- a/qemu-options.hx
17
+++ b/qemu-options.hx
12
+++ b/qemu-options.hx
18
@@ -XXX,XX +XXX,XX @@ qemu-system-i386 linux.img \
13
@@ -XXX,XX +XXX,XX @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
19
-netdev socket,id=n2,mcast=230.0.0.1:1234
14
"-netdev vhost-vdpa,id=str,vhostdev=/path/to/dev\n"
20
# launch yet another QEMU instance on same "bus"
15
" configure a vhost-vdpa network,Establish a vhost-vdpa netdev\n"
21
qemu-system-i386 linux.img \
16
#endif
22
- -device e1000,netdev=n3,macaddr=52:54:00:12:34:58 \
17
+#ifdef CONFIG_VMNET
23
+ -device e1000,netdev=n3,mac=52:54:00:12:34:58 \
18
+ "-netdev vmnet-host,id=str[,isolated=on|off][,net-uuid=uuid]\n"
24
-netdev socket,id=n3,mcast=230.0.0.1:1234
19
+ " [,start-address=addr,end-address=addr,subnet-mask=mask]\n"
25
@end example
20
+ " configure a vmnet network backend in host mode with ID 'str',\n"
26
21
+ " isolate this interface from others with 'isolated',\n"
22
+ " configure the address range and choose a subnet mask,\n"
23
+ " specify network UUID 'uuid' to disable DHCP and interact with\n"
24
+ " vmnet-host interfaces within this isolated network\n"
25
+ "-netdev vmnet-shared,id=str[,isolated=on|off][,nat66-prefix=addr]\n"
26
+ " [,start-address=addr,end-address=addr,subnet-mask=mask]\n"
27
+ " configure a vmnet network backend in shared mode with ID 'str',\n"
28
+ " configure the address range and choose a subnet mask,\n"
29
+ " set IPv6 ULA prefix (of length 64) to use for internal network,\n"
30
+ " isolate this interface from others with 'isolated'\n"
31
+ "-netdev vmnet-bridged,id=str,ifname=name[,isolated=on|off]\n"
32
+ " configure a vmnet network backend in bridged mode with ID 'str',\n"
33
+ " use 'ifname=name' to select a physical network interface to be bridged,\n"
34
+ " isolate this interface from others with 'isolated'\n"
35
+#endif
36
"-netdev hubport,id=str,hubid=n[,netdev=nd]\n"
37
" configure a hub port on the hub with ID 'n'\n", QEMU_ARCH_ALL)
38
DEF("nic", HAS_ARG, QEMU_OPTION_nic,
39
@@ -XXX,XX +XXX,XX @@ DEF("nic", HAS_ARG, QEMU_OPTION_nic,
40
#ifdef CONFIG_POSIX
41
"vhost-user|"
42
#endif
43
+#ifdef CONFIG_VMNET
44
+ "vmnet-host|vmnet-shared|vmnet-bridged|"
45
+#endif
46
"socket][,option][,...][mac=macaddr]\n"
47
" initialize an on-board / default host NIC (using MAC address\n"
48
" macaddr) and connect it to the given host network backend\n"
49
@@ -XXX,XX +XXX,XX @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
50
#ifdef CONFIG_NETMAP
51
"netmap|"
52
#endif
53
+#ifdef CONFIG_VMNET
54
+ "vmnet-host|vmnet-shared|vmnet-bridged|"
55
+#endif
56
"socket][,option][,option][,...]\n"
57
" old way to initialize a host network interface\n"
58
" (use the -netdev option if possible instead)\n", QEMU_ARCH_ALL)
27
--
59
--
28
2.5.0
60
2.7.4
29
61
30
62
diff view generated by jsdifflib
1
In ne2000_receive(), we try to assign size_ to size which converts
1
From: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
2
from size_t to integer. This will cause troubles when size_ is greater
3
INT_MAX, this will lead a negative value in size and it can then pass
4
the check of size < MIN_BUF_SIZE which may lead out of bound access of
5
for both buf and buf1.
6
2
7
Fixing by converting the type of size to size_t.
3
Signed-off-by: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
8
9
CC: qemu-stable@nongnu.org
10
Reported-by: Daniel Shapira <daniel@twistlock.com>
11
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
4
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
---
5
---
14
hw/net/ne2000.c | 4 ++--
6
MAINTAINERS | 5 +++++
15
1 file changed, 2 insertions(+), 2 deletions(-)
7
1 file changed, 5 insertions(+)
16
8
17
diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c
9
diff --git a/MAINTAINERS b/MAINTAINERS
18
index XXXXXXX..XXXXXXX 100644
10
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/net/ne2000.c
11
--- a/MAINTAINERS
20
+++ b/hw/net/ne2000.c
12
+++ b/MAINTAINERS
21
@@ -XXX,XX +XXX,XX @@ static int ne2000_buffer_full(NE2000State *s)
13
@@ -XXX,XX +XXX,XX @@ W: http://info.iet.unipi.it/~luigi/netmap/
22
ssize_t ne2000_receive(NetClientState *nc, const uint8_t *buf, size_t size_)
14
S: Maintained
23
{
15
F: net/netmap.c
24
NE2000State *s = qemu_get_nic_opaque(nc);
16
25
- int size = size_;
17
+Apple vmnet network backends
26
+ size_t size = size_;
18
+M: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
27
uint8_t *p;
19
+S: Maintained
28
unsigned int total_len, next, avail, len, index, mcast_idx;
20
+F: net/vmnet*
29
uint8_t buf1[60];
21
+
30
@@ -XXX,XX +XXX,XX @@ ssize_t ne2000_receive(NetClientState *nc, const uint8_t *buf, size_t size_)
22
Host Memory Backends
31
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
23
M: David Hildenbrand <david@redhat.com>
32
24
M: Igor Mammedov <imammedo@redhat.com>
33
#if defined(DEBUG_NE2000)
34
- printf("NE2000: received len=%d\n", size);
35
+ printf("NE2000: received len=%zu\n", size);
36
#endif
37
38
if (s->cmd & E8390_STOP || ne2000_buffer_full(s))
39
--
25
--
40
2.5.0
26
2.7.4
41
27
42
28
diff view generated by jsdifflib