1
The following changes since commit a04d91c701251a9b32b7364ddb48029ba024cb75:
1
The following changes since commit b6179aaff961627fcb59d7b234297966b81ac726:
2
2
3
Merge remote-tracking branch 'remotes/alistair/tags/pull-device-tree-20190327' into staging (2019-03-28 12:39:43 +0000)
3
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-cocoa-20190304' into staging (2019-03-04 16:50:41 +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 ab79237a15e8f8c23310291b672d83374cf17935:
9
for you to fetch changes up to 4b9b70000218640a42c3ea908a12665e5840b6cd:
10
10
11
net: tap: use qemu_set_nonblock (2019-03-29 15:22:18 +0800)
11
tests: Add a test for qemu self announcements (2019-03-05 11:27:41 +0800)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
14
15
Changes from V1:
16
- build fixes for qmp controlled announcing
17
15
----------------------------------------------------------------
18
----------------------------------------------------------------
16
Li Qiang (1):
19
Dr. David Alan Gilbert (9):
17
net: tap: use qemu_set_nonblock
20
net: Introduce announce timer
21
migration: Add announce parameters
22
virtio-net: Switch to using announce timer
23
migration: Switch to using announce timer
24
net: Add a network device specific self-announcement ability
25
virtio-net: Allow qemu_announce_self to trigger virtio announcements
26
qmp: Add announce-self command
27
hmp: Add hmp_announce_self
28
tests: Add a test for qemu self announcements
18
29
19
Marc-André Lureau (1):
30
Vincenzo Maffione (3):
20
net/socket: learn to talk with a unix dgram socket
31
net: netmap: small improvements netmap_send()
32
net: netmap: simplify netmap_receive()
33
net: netmap: improve netmap_receive_iov()
21
34
22
Zhang Chen (1):
35
Zhang Chen (1):
23
MAINTAINERS: Update the latest email address
36
net/colo-compare.c: Remove duplicated code
24
37
25
yuchenlin (1):
38
hmp-commands.hx | 16 +++++
26
e1000: Delay flush queue when receive RCTL
39
hmp.c | 33 ++++++++++
27
40
hmp.h | 1 +
28
MAINTAINERS | 2 +-
41
hw/net/trace-events | 6 ++
29
hw/net/e1000.c | 24 ++++++++++++++++++++++--
42
hw/net/virtio-net.c | 69 +++++++++++++++-----
30
net/socket.c | 25 +++++++++++++++++++++----
43
include/hw/virtio/virtio-net.h | 4 +-
31
net/tap.c | 10 +++++-----
44
include/migration/misc.h | 12 +---
32
4 files changed, 49 insertions(+), 12 deletions(-)
45
include/net/announce.h | 41 ++++++++++++
46
include/net/net.h | 2 +
47
include/qemu/typedefs.h | 1 +
48
include/sysemu/sysemu.h | 2 -
49
migration/migration.c | 103 +++++++++++++++++++++++++++++-
50
migration/migration.h | 4 ++
51
migration/savevm.c | 72 +--------------------
52
migration/trace-events | 1 -
53
net/Makefile.objs | 1 +
54
net/announce.c | 140 +++++++++++++++++++++++++++++++++++++++++
55
net/colo-compare.c | 8 ---
56
net/netmap.c | 110 ++++++++++++++------------------
57
net/trace-events | 3 +
58
qapi/migration.json | 53 +++++++++++++++-
59
qapi/net.json | 43 +++++++++++++
60
tests/Makefile.include | 3 +
61
tests/test-announce-self.c | 82 ++++++++++++++++++++++++
62
tests/test-hmp.c | 1 +
63
25 files changed, 637 insertions(+), 174 deletions(-)
64
create mode 100644 include/net/announce.h
65
create mode 100644 net/announce.c
66
create mode 100644 tests/test-announce-self.c
33
67
34
68
69
diff view generated by jsdifflib
1
From: Zhang Chen <chen.zhang@intel.com>
1
From: Zhang Chen <chen.zhang@intel.com>
2
2
3
Fix duplicated code:
4
https://bugs.launchpad.net/qemu/+bug/1811499
5
6
Reviewed-by: Thomas Huth <thuth@redhat.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
3
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
8
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
4
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
5
---
10
---
6
MAINTAINERS | 2 +-
11
net/colo-compare.c | 8 --------
7
1 file changed, 1 insertion(+), 1 deletion(-)
12
1 file changed, 8 deletions(-)
8
13
9
diff --git a/MAINTAINERS b/MAINTAINERS
14
diff --git a/net/colo-compare.c b/net/colo-compare.c
10
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
11
--- a/MAINTAINERS
16
--- a/net/colo-compare.c
12
+++ b/MAINTAINERS
17
+++ b/net/colo-compare.c
13
@@ -XXX,XX +XXX,XX @@ F: include/migration/failover.h
18
@@ -XXX,XX +XXX,XX @@ static bool colo_mark_tcp_pkt(Packet *ppkt, Packet *spkt,
14
F: docs/COLO-FT.txt
19
return true;
15
20
}
16
COLO Proxy
21
}
17
-M: Zhang Chen <zhangckid@gmail.com>
22
- if (ppkt->tcp_seq == spkt->tcp_seq && ppkt->seq_end == spkt->seq_end) {
18
+M: Zhang Chen <chen.zhang@intel.com>
23
- if (colo_compare_packet_payload(ppkt, spkt,
19
M: Li Zhijian <lizhijian@cn.fujitsu.com>
24
- ppkt->header_size, spkt->header_size,
20
S: Supported
25
- ppkt->payload_size)) {
21
F: docs/colo-proxy.txt
26
- *mark = COLO_COMPARE_FREE_SECONDARY | COLO_COMPARE_FREE_PRIMARY;
27
- return true;
28
- }
29
- }
30
31
/* one part of secondary packet payload still need to be compared */
32
if (!after(ppkt->seq_end, spkt->seq_end)) {
22
--
33
--
23
2.5.0
34
2.5.0
24
35
25
36
diff view generated by jsdifflib
New patch
1
From: Vincenzo Maffione <v.maffione@gmail.com>
1
2
3
This change improves the handling of incomplete multi-slot packets
4
(e.g. with the NS_MOREFRAG set), by advancing ring->head only on
5
complete packets. The ring->cur pointer is advanced in any case in
6
order to acknowledge the kernel and move the wake-up point (thus
7
avoiding repeated wake-ups).
8
Also don't be verbose when incomplete packets are found.
9
10
Signed-off-by: Vincenzo Maffione <v.maffione@gmail.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
13
net/netmap.c | 31 +++++++++++++++++++------------
14
1 file changed, 19 insertions(+), 12 deletions(-)
15
16
diff --git a/net/netmap.c b/net/netmap.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/net/netmap.c
19
+++ b/net/netmap.c
20
@@ -XXX,XX +XXX,XX @@ static void netmap_send(void *opaque)
21
{
22
NetmapState *s = opaque;
23
struct netmap_ring *ring = s->rx;
24
+ unsigned int tail = ring->tail;
25
26
- /* Keep sending while there are available packets into the netmap
27
+ /* Keep sending while there are available slots in the netmap
28
RX ring and the forwarding path towards the peer is open. */
29
- while (!nm_ring_empty(ring)) {
30
- uint32_t i;
31
+ while (ring->head != tail) {
32
+ uint32_t i = ring->head;
33
uint32_t idx;
34
bool morefrag;
35
int iovcnt = 0;
36
int iovsize;
37
38
+ /* Get a (possibly multi-slot) packet. */
39
do {
40
- i = ring->cur;
41
idx = ring->slot[i].buf_idx;
42
morefrag = (ring->slot[i].flags & NS_MOREFRAG);
43
- s->iov[iovcnt].iov_base = (u_char *)NETMAP_BUF(ring, idx);
44
+ s->iov[iovcnt].iov_base = (void *)NETMAP_BUF(ring, idx);
45
s->iov[iovcnt].iov_len = ring->slot[i].len;
46
iovcnt++;
47
+ i = nm_ring_next(ring, i);
48
+ } while (i != tail && morefrag);
49
50
- ring->cur = ring->head = nm_ring_next(ring, i);
51
- } while (!nm_ring_empty(ring) && morefrag);
52
+ /* Advance ring->cur to tell the kernel that we have seen the slots. */
53
+ ring->cur = i;
54
55
- if (unlikely(nm_ring_empty(ring) && morefrag)) {
56
- RD(5, "[netmap_send] ran out of slots, with a pending"
57
- "incomplete packet\n");
58
+ if (unlikely(morefrag)) {
59
+ /* This is a truncated packet, so we can stop without releasing the
60
+ * incomplete slots by updating ring->head. We will hopefully
61
+ * re-read the complete packet the next time we are called. */
62
+ break;
63
}
64
65
iovsize = qemu_sendv_packet_async(&s->nc, s->iov, iovcnt,
66
netmap_send_completed);
67
68
+ /* Release the slots to the kernel. */
69
+ ring->head = i;
70
+
71
if (iovsize == 0) {
72
/* The peer does not receive anymore. Packet is queued, stop
73
- * reading from the backend until netmap_send_completed()
74
- */
75
+ * reading from the backend until netmap_send_completed(). */
76
netmap_read_poll(s, false);
77
break;
78
}
79
--
80
2.5.0
81
82
diff view generated by jsdifflib
New patch
1
From: Vincenzo Maffione <v.maffione@gmail.com>
1
2
3
Improve code reuse by implementing netmap_receive() with a call
4
to netmap_receive_iov().
5
6
Signed-off-by: Vincenzo Maffione <v.maffione@gmail.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
9
net/netmap.c | 50 +++++++++++---------------------------------------
10
1 file changed, 11 insertions(+), 39 deletions(-)
11
12
diff --git a/net/netmap.c b/net/netmap.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/net/netmap.c
15
+++ b/net/netmap.c
16
@@ -XXX,XX +XXX,XX @@ static void netmap_writable(void *opaque)
17
qemu_flush_queued_packets(&s->nc);
18
}
19
20
-static ssize_t netmap_receive(NetClientState *nc,
21
- const uint8_t *buf, size_t size)
22
-{
23
- NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
24
- struct netmap_ring *ring = s->tx;
25
- uint32_t i;
26
- uint32_t idx;
27
- uint8_t *dst;
28
-
29
- if (unlikely(!ring)) {
30
- /* Drop. */
31
- return size;
32
- }
33
-
34
- if (unlikely(size > ring->nr_buf_size)) {
35
- RD(5, "[netmap_receive] drop packet of size %d > %d\n",
36
- (int)size, ring->nr_buf_size);
37
- return size;
38
- }
39
-
40
- if (nm_ring_empty(ring)) {
41
- /* No available slots in the netmap TX ring. */
42
- netmap_write_poll(s, true);
43
- return 0;
44
- }
45
-
46
- i = ring->cur;
47
- idx = ring->slot[i].buf_idx;
48
- dst = (uint8_t *)NETMAP_BUF(ring, idx);
49
-
50
- ring->slot[i].len = size;
51
- ring->slot[i].flags = 0;
52
- pkt_copy(buf, dst, size);
53
- ring->cur = ring->head = nm_ring_next(ring, i);
54
- ioctl(s->nmd->fd, NIOCTXSYNC, NULL);
55
-
56
- return size;
57
-}
58
-
59
static ssize_t netmap_receive_iov(NetClientState *nc,
60
const struct iovec *iov, int iovcnt)
61
{
62
@@ -XXX,XX +XXX,XX @@ static ssize_t netmap_receive_iov(NetClientState *nc,
63
return iov_size(iov, iovcnt);
64
}
65
66
+static ssize_t netmap_receive(NetClientState *nc,
67
+ const uint8_t *buf, size_t size)
68
+{
69
+ struct iovec iov;
70
+
71
+ iov.iov_base = (void *)buf;
72
+ iov.iov_len = size;
73
+
74
+ return netmap_receive_iov(nc, &iov, 1);
75
+}
76
+
77
/* Complete a previous send (backend --> guest) and enable the
78
fd_read callback. */
79
static void netmap_send_completed(NetClientState *nc, ssize_t len)
80
--
81
2.5.0
82
83
diff view generated by jsdifflib
New patch
1
From: Vincenzo Maffione <v.maffione@gmail.com>
1
2
3
Changes:
4
- Save CPU cycles by computing the return value while scanning the
5
input iovec, rather than calling iov_size() at the end.
6
- Remove check for s->tx != NULL, because it cannot happen.
7
- Cache ring->tail in a local variable and use it to check for
8
space in the TX ring. The use of nm_ring_empty() was invalid,
9
because nobody is updating ring->cur and ring->head at that point.
10
- In case we run out of netmap slots in the middle of a packet,
11
move the wake-up point by advancing ring->cur, but do not
12
expose the incomplete packet (i.e., by updating also ring->head).
13
14
Signed-off-by: Vincenzo Maffione <v.maffione@gmail.com>
15
Signed-off-by: Jason Wang <jasowang@redhat.com>
16
---
17
net/netmap.c | 29 +++++++++++++++++------------
18
1 file changed, 17 insertions(+), 12 deletions(-)
19
20
diff --git a/net/netmap.c b/net/netmap.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/net/netmap.c
23
+++ b/net/netmap.c
24
@@ -XXX,XX +XXX,XX @@ static ssize_t netmap_receive_iov(NetClientState *nc,
25
{
26
NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
27
struct netmap_ring *ring = s->tx;
28
+ unsigned int tail = ring->tail;
29
+ ssize_t totlen = 0;
30
uint32_t last;
31
uint32_t idx;
32
uint8_t *dst;
33
int j;
34
uint32_t i;
35
36
- if (unlikely(!ring)) {
37
- /* Drop the packet. */
38
- return iov_size(iov, iovcnt);
39
- }
40
-
41
- last = i = ring->cur;
42
+ last = i = ring->head;
43
44
if (nm_ring_space(ring) < iovcnt) {
45
- /* Not enough netmap slots. */
46
+ /* Not enough netmap slots. Tell the kernel that we have seen the new
47
+ * available slots (so that it notifies us again when it has more
48
+ * ones), but without publishing any new slots to be processed
49
+ * (e.g., we don't advance ring->head). */
50
+ ring->cur = tail;
51
netmap_write_poll(s, true);
52
return 0;
53
}
54
@@ -XXX,XX +XXX,XX @@ static ssize_t netmap_receive_iov(NetClientState *nc,
55
int offset = 0;
56
int nm_frag_size;
57
58
+ totlen += iov_frag_size;
59
+
60
/* Split each iovec fragment over more netmap slots, if
61
necessary. */
62
while (iov_frag_size) {
63
nm_frag_size = MIN(iov_frag_size, ring->nr_buf_size);
64
65
- if (unlikely(nm_ring_empty(ring))) {
66
- /* We run out of netmap slots while splitting the
67
+ if (unlikely(i == tail)) {
68
+ /* We ran out of netmap slots while splitting the
69
iovec fragments. */
70
+ ring->cur = tail;
71
netmap_write_poll(s, true);
72
return 0;
73
}
74
@@ -XXX,XX +XXX,XX @@ static ssize_t netmap_receive_iov(NetClientState *nc,
75
/* The last slot must not have NS_MOREFRAG set. */
76
ring->slot[last].flags &= ~NS_MOREFRAG;
77
78
- /* Now update ring->cur and ring->head. */
79
- ring->cur = ring->head = i;
80
+ /* Now update ring->head and ring->cur to publish the new slots and
81
+ * the new wakeup point. */
82
+ ring->head = ring->cur = i;
83
84
ioctl(s->nmd->fd, NIOCTXSYNC, NULL);
85
86
- return iov_size(iov, iovcnt);
87
+ return totlen;
88
}
89
90
static ssize_t netmap_receive(NetClientState *nc,
91
--
92
2.5.0
93
94
diff view generated by jsdifflib
New patch
1
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
2
3
The 'announce timer' will be used by migration, and explicit
4
requests for qemu to perform network announces.
5
6
Based on the work by Germano Veit Michel <germano@redhat.com>
7
and Vlad Yasevich <vyasevic@redhat.com>
8
9
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
10
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
13
include/net/announce.h | 39 ++++++++++++++++++++++++++++++++
14
include/qemu/typedefs.h | 1 +
15
migration/migration.c | 1 +
16
net/Makefile.objs | 1 +
17
net/announce.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++
18
qapi/net.json | 23 +++++++++++++++++++
19
6 files changed, 125 insertions(+)
20
create mode 100644 include/net/announce.h
21
create mode 100644 net/announce.c
22
23
diff --git a/include/net/announce.h b/include/net/announce.h
24
new file mode 100644
25
index XXXXXXX..XXXXXXX
26
--- /dev/null
27
+++ b/include/net/announce.h
28
@@ -XXX,XX +XXX,XX @@
29
+/*
30
+ * Self-announce facility
31
+ * (c) 2017-2019 Red Hat, Inc.
32
+ *
33
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
34
+ * See the COPYING file in the top-level directory.
35
+ */
36
+
37
+#ifndef QEMU_NET_ANNOUNCE_H
38
+#define QEMU_NET_ANNOUNCE_H
39
+
40
+#include "qemu-common.h"
41
+#include "qapi/qapi-types-net.h"
42
+#include "qemu/timer.h"
43
+
44
+struct AnnounceTimer {
45
+ QEMUTimer *tm;
46
+ AnnounceParameters params;
47
+ QEMUClockType type;
48
+ int round;
49
+};
50
+
51
+/* Returns: update the timer to the next time point */
52
+int64_t qemu_announce_timer_step(AnnounceTimer *timer);
53
+
54
+/* Delete the underlying timer */
55
+void qemu_announce_timer_del(AnnounceTimer *timer);
56
+
57
+/*
58
+ * Under BQL/main thread
59
+ * Reset the timer to the given parameters/type/notifier.
60
+ */
61
+void qemu_announce_timer_reset(AnnounceTimer *timer,
62
+ AnnounceParameters *params,
63
+ QEMUClockType type,
64
+ QEMUTimerCB *cb,
65
+ void *opaque);
66
+
67
+#endif
68
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
69
index XXXXXXX..XXXXXXX 100644
70
--- a/include/qemu/typedefs.h
71
+++ b/include/qemu/typedefs.h
72
@@ -XXX,XX +XXX,XX @@
73
typedef struct AdapterInfo AdapterInfo;
74
typedef struct AddressSpace AddressSpace;
75
typedef struct AioContext AioContext;
76
+typedef struct AnnounceTimer AnnounceTimer;
77
typedef struct BdrvDirtyBitmap BdrvDirtyBitmap;
78
typedef struct BdrvDirtyBitmapIter BdrvDirtyBitmapIter;
79
typedef struct BlockBackend BlockBackend;
80
diff --git a/migration/migration.c b/migration/migration.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/migration/migration.c
83
+++ b/migration/migration.c
84
@@ -XXX,XX +XXX,XX @@
85
#include "migration/colo.h"
86
#include "hw/boards.h"
87
#include "monitor/monitor.h"
88
+#include "net/announce.h"
89
90
#define MAX_THROTTLE (32 << 20) /* Migration transfer speed throttling */
91
92
diff --git a/net/Makefile.objs b/net/Makefile.objs
93
index XXXXXXX..XXXXXXX 100644
94
--- a/net/Makefile.objs
95
+++ b/net/Makefile.objs
96
@@ -XXX,XX +XXX,XX @@ common-obj-y = net.o queue.o checksum.o util.o hub.o
97
common-obj-y += socket.o
98
common-obj-y += dump.o
99
common-obj-y += eth.o
100
+common-obj-y += announce.o
101
common-obj-$(CONFIG_L2TPV3) += l2tpv3.o
102
common-obj-$(call land,$(CONFIG_VIRTIO_NET),$(CONFIG_VHOST_NET_USER)) += vhost-user.o
103
common-obj-$(call land,$(call lnot,$(CONFIG_VIRTIO_NET)),$(CONFIG_VHOST_NET_USER)) += vhost-user-stub.o
104
diff --git a/net/announce.c b/net/announce.c
105
new file mode 100644
106
index XXXXXXX..XXXXXXX
107
--- /dev/null
108
+++ b/net/announce.c
109
@@ -XXX,XX +XXX,XX @@
110
+/*
111
+ * Self-announce
112
+ * (c) 2017-2019 Red Hat, Inc.
113
+ *
114
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
115
+ * See the COPYING file in the top-level directory.
116
+ */
117
+
118
+#include "qemu/osdep.h"
119
+#include "qemu-common.h"
120
+#include "net/announce.h"
121
+#include "qapi/clone-visitor.h"
122
+#include "qapi/qapi-visit-net.h"
123
+
124
+int64_t qemu_announce_timer_step(AnnounceTimer *timer)
125
+{
126
+ int64_t step;
127
+
128
+ step = timer->params.initial +
129
+ (timer->params.rounds - timer->round - 1) *
130
+ timer->params.step;
131
+
132
+ if (step < 0 || step > timer->params.max) {
133
+ step = timer->params.max;
134
+ }
135
+ timer_mod(timer->tm, qemu_clock_get_ms(timer->type) + step);
136
+
137
+ return step;
138
+}
139
+
140
+void qemu_announce_timer_del(AnnounceTimer *timer)
141
+{
142
+ if (timer->tm) {
143
+ timer_del(timer->tm);
144
+ timer_free(timer->tm);
145
+ timer->tm = NULL;
146
+ }
147
+}
148
+
149
+/*
150
+ * Under BQL/main thread
151
+ * Reset the timer to the given parameters/type/notifier.
152
+ */
153
+void qemu_announce_timer_reset(AnnounceTimer *timer,
154
+ AnnounceParameters *params,
155
+ QEMUClockType type,
156
+ QEMUTimerCB *cb,
157
+ void *opaque)
158
+{
159
+ /*
160
+ * We're under the BQL, so the current timer can't
161
+ * be firing, so we should be able to delete it.
162
+ */
163
+ qemu_announce_timer_del(timer);
164
+
165
+ QAPI_CLONE_MEMBERS(AnnounceParameters, &timer->params, params);
166
+ timer->round = params->rounds;
167
+ timer->type = type;
168
+ timer->tm = timer_new_ms(type, cb, opaque);
169
+}
170
diff --git a/qapi/net.json b/qapi/net.json
171
index XXXXXXX..XXXXXXX 100644
172
--- a/qapi/net.json
173
+++ b/qapi/net.json
174
@@ -XXX,XX +XXX,XX @@
175
##
176
{ 'event': 'NIC_RX_FILTER_CHANGED',
177
'data': { '*name': 'str', 'path': 'str' } }
178
+
179
+##
180
+# @AnnounceParameters:
181
+#
182
+# Parameters for self-announce timers
183
+#
184
+# @initial: Initial delay (in ms) before sending the first GARP/RARP
185
+# announcement
186
+#
187
+# @max: Maximum delay (in ms) between GARP/RARP announcement packets
188
+#
189
+# @rounds: Number of self-announcement attempts
190
+#
191
+# @step: Delay increase (in ms) after each self-announcement attempt
192
+#
193
+# Since: 4.0
194
+##
195
+
196
+{ 'struct': 'AnnounceParameters',
197
+ 'data': { 'initial': 'int',
198
+ 'max': 'int',
199
+ 'rounds': 'int',
200
+ 'step': 'int' } }
201
--
202
2.5.0
203
204
diff view generated by jsdifflib
New patch
1
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
2
3
Add migration parameters that control RARP/GARP announcement timeouts.
4
5
Based on earlier patches by myself and
6
Vladislav Yasevich <vyasevic@redhat.com>
7
8
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
9
Acked-by: Markus Armbruster <armbru@redhat.com>
10
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
13
hmp.c | 28 +++++++++++++
14
include/migration/misc.h | 2 +
15
migration/migration.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++
16
qapi/migration.json | 53 +++++++++++++++++++++++--
17
4 files changed, 180 insertions(+), 3 deletions(-)
18
19
diff --git a/hmp.c b/hmp.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/hmp.c
22
+++ b/hmp.c
23
@@ -XXX,XX +XXX,XX @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict)
24
params = qmp_query_migrate_parameters(NULL);
25
26
if (params) {
27
+ monitor_printf(mon, "%s: %" PRIu64 " ms\n",
28
+ MigrationParameter_str(MIGRATION_PARAMETER_ANNOUNCE_INITIAL),
29
+ params->announce_initial);
30
+ monitor_printf(mon, "%s: %" PRIu64 " ms\n",
31
+ MigrationParameter_str(MIGRATION_PARAMETER_ANNOUNCE_MAX),
32
+ params->announce_max);
33
+ monitor_printf(mon, "%s: %" PRIu64 "\n",
34
+ MigrationParameter_str(MIGRATION_PARAMETER_ANNOUNCE_ROUNDS),
35
+ params->announce_rounds);
36
+ monitor_printf(mon, "%s: %" PRIu64 " ms\n",
37
+ MigrationParameter_str(MIGRATION_PARAMETER_ANNOUNCE_STEP),
38
+ params->announce_step);
39
assert(params->has_compress_level);
40
monitor_printf(mon, "%s: %u\n",
41
MigrationParameter_str(MIGRATION_PARAMETER_COMPRESS_LEVEL),
42
@@ -XXX,XX +XXX,XX @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
43
p->has_max_postcopy_bandwidth = true;
44
visit_type_size(v, param, &p->max_postcopy_bandwidth, &err);
45
break;
46
+ case MIGRATION_PARAMETER_ANNOUNCE_INITIAL:
47
+ p->has_announce_initial = true;
48
+ visit_type_size(v, param, &p->announce_initial, &err);
49
+ break;
50
+ case MIGRATION_PARAMETER_ANNOUNCE_MAX:
51
+ p->has_announce_max = true;
52
+ visit_type_size(v, param, &p->announce_max, &err);
53
+ break;
54
+ case MIGRATION_PARAMETER_ANNOUNCE_ROUNDS:
55
+ p->has_announce_rounds = true;
56
+ visit_type_size(v, param, &p->announce_rounds, &err);
57
+ break;
58
+ case MIGRATION_PARAMETER_ANNOUNCE_STEP:
59
+ p->has_announce_step = true;
60
+ visit_type_size(v, param, &p->announce_step, &err);
61
+ break;
62
default:
63
assert(0);
64
}
65
diff --git a/include/migration/misc.h b/include/migration/misc.h
66
index XXXXXXX..XXXXXXX 100644
67
--- a/include/migration/misc.h
68
+++ b/include/migration/misc.h
69
@@ -XXX,XX +XXX,XX @@
70
#define MIGRATION_MISC_H
71
72
#include "qemu/notify.h"
73
+#include "qapi/qapi-types-net.h"
74
75
/* migration/ram.c */
76
77
@@ -XXX,XX +XXX,XX @@ int64_t self_announce_delay(int round)
78
return 50 + (SELF_ANNOUNCE_ROUNDS - round - 1) * 100;
79
}
80
81
+AnnounceParameters *migrate_announce_params(void);
82
/* migration/savevm.c */
83
84
void dump_vmstate_json_to_file(FILE *out_fp);
85
diff --git a/migration/migration.c b/migration/migration.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/migration/migration.c
88
+++ b/migration/migration.c
89
@@ -XXX,XX +XXX,XX @@
90
*/
91
#define DEFAULT_MIGRATE_MAX_POSTCOPY_BANDWIDTH 0
92
93
+/*
94
+ * Parameters for self_announce_delay giving a stream of RARP/ARP
95
+ * packets after migration.
96
+ */
97
+#define DEFAULT_MIGRATE_ANNOUNCE_INITIAL 50
98
+#define DEFAULT_MIGRATE_ANNOUNCE_MAX 550
99
+#define DEFAULT_MIGRATE_ANNOUNCE_ROUNDS 5
100
+#define DEFAULT_MIGRATE_ANNOUNCE_STEP 100
101
+
102
static NotifierList migration_state_notifiers =
103
NOTIFIER_LIST_INITIALIZER(migration_state_notifiers);
104
105
@@ -XXX,XX +XXX,XX @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp)
106
params->max_postcopy_bandwidth = s->parameters.max_postcopy_bandwidth;
107
params->has_max_cpu_throttle = true;
108
params->max_cpu_throttle = s->parameters.max_cpu_throttle;
109
+ params->has_announce_initial = true;
110
+ params->announce_initial = s->parameters.announce_initial;
111
+ params->has_announce_max = true;
112
+ params->announce_max = s->parameters.announce_max;
113
+ params->has_announce_rounds = true;
114
+ params->announce_rounds = s->parameters.announce_rounds;
115
+ params->has_announce_step = true;
116
+ params->announce_step = s->parameters.announce_step;
117
118
return params;
119
}
120
121
+AnnounceParameters *migrate_announce_params(void)
122
+{
123
+ static AnnounceParameters ap;
124
+
125
+ MigrationState *s = migrate_get_current();
126
+
127
+ ap.initial = s->parameters.announce_initial;
128
+ ap.max = s->parameters.announce_max;
129
+ ap.rounds = s->parameters.announce_rounds;
130
+ ap.step = s->parameters.announce_step;
131
+
132
+ return &ap;
133
+}
134
+
135
/*
136
* Return true if we're already in the middle of a migration
137
* (i.e. any of the active or setup states)
138
@@ -XXX,XX +XXX,XX @@ static bool migrate_params_check(MigrationParameters *params, Error **errp)
139
return false;
140
}
141
142
+ if (params->has_announce_initial &&
143
+ params->announce_initial > 100000) {
144
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
145
+ "announce_initial",
146
+ "is invalid, it must be less than 100000 ms");
147
+ return false;
148
+ }
149
+ if (params->has_announce_max &&
150
+ params->announce_max > 100000) {
151
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
152
+ "announce_max",
153
+ "is invalid, it must be less than 100000 ms");
154
+ return false;
155
+ }
156
+ if (params->has_announce_rounds &&
157
+ params->announce_rounds > 1000) {
158
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
159
+ "announce_rounds",
160
+ "is invalid, it must be in the range of 0 to 1000");
161
+ return false;
162
+ }
163
+ if (params->has_announce_step &&
164
+ (params->announce_step < 1 ||
165
+ params->announce_step > 10000)) {
166
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
167
+ "announce_step",
168
+ "is invalid, it must be in the range of 1 to 10000 ms");
169
+ return false;
170
+ }
171
return true;
172
}
173
174
@@ -XXX,XX +XXX,XX @@ static void migrate_params_test_apply(MigrateSetParameters *params,
175
if (params->has_max_cpu_throttle) {
176
dest->max_cpu_throttle = params->max_cpu_throttle;
177
}
178
+ if (params->has_announce_initial) {
179
+ dest->announce_initial = params->announce_initial;
180
+ }
181
+ if (params->has_announce_max) {
182
+ dest->announce_max = params->announce_max;
183
+ }
184
+ if (params->has_announce_rounds) {
185
+ dest->announce_rounds = params->announce_rounds;
186
+ }
187
+ if (params->has_announce_step) {
188
+ dest->announce_step = params->announce_step;
189
+ }
190
}
191
192
static void migrate_params_apply(MigrateSetParameters *params, Error **errp)
193
@@ -XXX,XX +XXX,XX @@ static void migrate_params_apply(MigrateSetParameters *params, Error **errp)
194
if (params->has_max_cpu_throttle) {
195
s->parameters.max_cpu_throttle = params->max_cpu_throttle;
196
}
197
+ if (params->has_announce_initial) {
198
+ s->parameters.announce_initial = params->announce_initial;
199
+ }
200
+ if (params->has_announce_max) {
201
+ s->parameters.announce_max = params->announce_max;
202
+ }
203
+ if (params->has_announce_rounds) {
204
+ s->parameters.announce_rounds = params->announce_rounds;
205
+ }
206
+ if (params->has_announce_step) {
207
+ s->parameters.announce_step = params->announce_step;
208
+ }
209
}
210
211
void qmp_migrate_set_parameters(MigrateSetParameters *params, Error **errp)
212
@@ -XXX,XX +XXX,XX @@ static Property migration_properties[] = {
213
DEFINE_PROP_UINT8("max-cpu-throttle", MigrationState,
214
parameters.max_cpu_throttle,
215
DEFAULT_MIGRATE_MAX_CPU_THROTTLE),
216
+ DEFINE_PROP_SIZE("announce-initial", MigrationState,
217
+ parameters.announce_initial,
218
+ DEFAULT_MIGRATE_ANNOUNCE_INITIAL),
219
+ DEFINE_PROP_SIZE("announce-max", MigrationState,
220
+ parameters.announce_max,
221
+ DEFAULT_MIGRATE_ANNOUNCE_MAX),
222
+ DEFINE_PROP_SIZE("announce-rounds", MigrationState,
223
+ parameters.announce_rounds,
224
+ DEFAULT_MIGRATE_ANNOUNCE_ROUNDS),
225
+ DEFINE_PROP_SIZE("announce-step", MigrationState,
226
+ parameters.announce_step,
227
+ DEFAULT_MIGRATE_ANNOUNCE_STEP),
228
229
/* Migration capabilities */
230
DEFINE_PROP_MIG_CAP("x-xbzrle", MIGRATION_CAPABILITY_XBZRLE),
231
@@ -XXX,XX +XXX,XX @@ static void migration_instance_init(Object *obj)
232
params->has_xbzrle_cache_size = true;
233
params->has_max_postcopy_bandwidth = true;
234
params->has_max_cpu_throttle = true;
235
+ params->has_announce_initial = true;
236
+ params->has_announce_max = true;
237
+ params->has_announce_rounds = true;
238
+ params->has_announce_step = true;
239
240
qemu_sem_init(&ms->postcopy_pause_sem, 0);
241
qemu_sem_init(&ms->postcopy_pause_rp_sem, 0);
242
diff --git a/qapi/migration.json b/qapi/migration.json
243
index XXXXXXX..XXXXXXX 100644
244
--- a/qapi/migration.json
245
+++ b/qapi/migration.json
246
@@ -XXX,XX +XXX,XX @@
247
#
248
# Migration parameters enumeration
249
#
250
+# @announce-initial: Initial delay (in milliseconds) before sending the first
251
+# announce (Since 4.0)
252
+#
253
+# @announce-max: Maximum delay (in milliseconds) between packets in the
254
+# announcement (Since 4.0)
255
+#
256
+# @announce-rounds: Number of self-announce packets sent after migration
257
+# (Since 4.0)
258
+#
259
+# @announce-step: Increase in delay (in milliseconds) between subsequent
260
+# packets in the announcement (Since 4.0)
261
+#
262
# @compress-level: Set the compression level to be used in live migration,
263
# the compression level is an integer between 0 and 9, where 0 means
264
# no compression, 1 means the best compression speed, and 9 means best
265
@@ -XXX,XX +XXX,XX @@
266
#
267
# @max-cpu-throttle: maximum cpu throttle percentage.
268
# Defaults to 99. (Since 3.1)
269
+#
270
# Since: 2.4
271
##
272
{ 'enum': 'MigrationParameter',
273
- 'data': ['compress-level', 'compress-threads', 'decompress-threads',
274
+ 'data': ['announce-initial', 'announce-max',
275
+ 'announce-rounds', 'announce-step',
276
+ 'compress-level', 'compress-threads', 'decompress-threads',
277
'compress-wait-thread',
278
'cpu-throttle-initial', 'cpu-throttle-increment',
279
'tls-creds', 'tls-hostname', 'max-bandwidth',
280
@@ -XXX,XX +XXX,XX @@
281
##
282
# @MigrateSetParameters:
283
#
284
+# @announce-initial: Initial delay (in milliseconds) before sending the first
285
+# announce (Since 4.0)
286
+#
287
+# @announce-max: Maximum delay (in milliseconds) between packets in the
288
+# announcement (Since 4.0)
289
+#
290
+# @announce-rounds: Number of self-announce packets sent after migration
291
+# (Since 4.0)
292
+#
293
+# @announce-step: Increase in delay (in milliseconds) between subsequent
294
+# packets in the announcement (Since 4.0)
295
+#
296
# @compress-level: compression level
297
#
298
# @compress-threads: compression thread count
299
@@ -XXX,XX +XXX,XX @@
300
# TODO either fuse back into MigrationParameters, or make
301
# MigrationParameters members mandatory
302
{ 'struct': 'MigrateSetParameters',
303
- 'data': { '*compress-level': 'int',
304
+ 'data': { '*announce-initial': 'size',
305
+ '*announce-max': 'size',
306
+ '*announce-rounds': 'size',
307
+ '*announce-step': 'size',
308
+ '*compress-level': 'int',
309
'*compress-threads': 'int',
310
'*compress-wait-thread': 'bool',
311
'*decompress-threads': 'int',
312
@@ -XXX,XX +XXX,XX @@
313
#
314
# The optional members aren't actually optional.
315
#
316
+# @announce-initial: Initial delay (in milliseconds) before sending the
317
+# first announce (Since 4.0)
318
+#
319
+# @announce-max: Maximum delay (in milliseconds) between packets in the
320
+# announcement (Since 4.0)
321
+#
322
+# @announce-rounds: Number of self-announce packets sent after migration
323
+# (Since 4.0)
324
+#
325
+# @announce-step: Increase in delay (in milliseconds) between subsequent
326
+# packets in the announcement (Since 4.0)
327
+#
328
# @compress-level: compression level
329
#
330
# @compress-threads: compression thread count
331
@@ -XXX,XX +XXX,XX @@
332
# Since: 2.4
333
##
334
{ 'struct': 'MigrationParameters',
335
- 'data': { '*compress-level': 'uint8',
336
+ 'data': { '*announce-initial': 'size',
337
+ '*announce-max': 'size',
338
+ '*announce-rounds': 'size',
339
+ '*announce-step': 'size',
340
+ '*compress-level': 'uint8',
341
'*compress-threads': 'uint8',
342
'*compress-wait-thread': 'bool',
343
'*decompress-threads': 'uint8',
344
--
345
2.5.0
346
347
diff view generated by jsdifflib
1
From: Li Qiang <liq3ea@gmail.com>
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
2
2
3
The fcntl will change the flags directly, use qemu_set_nonblock()
3
Switch virtio's self announcement to use the AnnounceTimer.
4
instead.
4
It keeps it's own AnnounceTimer (per device), and starts running it
5
using a migration post-load and a virtual clock; that way the
6
announce happens once the guest is actually running.
7
The timer uses the migration parameters to set the timing of
8
the repeats.
5
9
6
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
10
Based on earlier patches by myself and
7
Acked-by: Michael S. Tsirkin <mst@redhat.com>
11
Vladislav Yasevich <vyasevic@redhat.com>
8
Signed-off-by: Li Qiang <liq3ea@gmail.com>
12
13
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
14
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
15
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
16
---
11
net/tap.c | 10 +++++-----
17
hw/net/trace-events | 5 +++++
12
1 file changed, 5 insertions(+), 5 deletions(-)
18
hw/net/virtio-net.c | 36 +++++++++++++++++++++++-------------
19
include/hw/virtio/virtio-net.h | 4 ++--
20
3 files changed, 30 insertions(+), 15 deletions(-)
13
21
14
diff --git a/net/tap.c b/net/tap.c
22
diff --git a/hw/net/trace-events b/hw/net/trace-events
15
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
16
--- a/net/tap.c
24
--- a/hw/net/trace-events
17
+++ b/net/tap.c
25
+++ b/hw/net/trace-events
18
@@ -XXX,XX +XXX,XX @@ int net_init_bridge(const Netdev *netdev, const char *name,
26
@@ -XXX,XX +XXX,XX @@ sunhme_rx_filter_reject(void) "rejecting incoming frame"
19
return -1;
27
sunhme_rx_filter_accept(void) "accepting incoming frame"
28
sunhme_rx_desc(uint32_t addr, int offset, uint32_t status, int len, int cr, int nr) "addr 0x%"PRIx32"(+0x%x) status 0x%"PRIx32 " len %d (ring %d/%d)"
29
sunhme_rx_xsum_calc(uint16_t xsum) "calculated incoming xsum as 0x%x"
30
+
31
+# hw/net/virtio-net.c
32
+virtio_net_announce_timer(int round) "%d"
33
+virtio_net_handle_announce(int round) "%d"
34
+virtio_net_post_load_device(void)
35
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/net/virtio-net.c
38
+++ b/hw/net/virtio-net.c
39
@@ -XXX,XX +XXX,XX @@
40
#include "qemu/timer.h"
41
#include "hw/virtio/virtio-net.h"
42
#include "net/vhost_net.h"
43
+#include "net/announce.h"
44
#include "hw/virtio/virtio-bus.h"
45
#include "qapi/error.h"
46
#include "qapi/qapi-events-net.h"
47
#include "hw/virtio/virtio-access.h"
48
#include "migration/misc.h"
49
#include "standard-headers/linux/ethtool.h"
50
+#include "trace.h"
51
52
#define VIRTIO_NET_VM_VERSION 11
53
54
@@ -XXX,XX +XXX,XX @@ static void virtio_net_announce_timer(void *opaque)
55
{
56
VirtIONet *n = opaque;
57
VirtIODevice *vdev = VIRTIO_DEVICE(n);
58
+ trace_virtio_net_announce_timer(n->announce_timer.round);
59
60
- n->announce_counter--;
61
+ n->announce_timer.round--;
62
n->status |= VIRTIO_NET_S_ANNOUNCE;
63
virtio_notify_config(vdev);
64
}
65
@@ -XXX,XX +XXX,XX @@ static void virtio_net_reset(VirtIODevice *vdev)
66
n->nobcast = 0;
67
/* multiqueue is disabled by default */
68
n->curr_queues = 1;
69
- timer_del(n->announce_timer);
70
- n->announce_counter = 0;
71
+ timer_del(n->announce_timer.tm);
72
+ n->announce_timer.round = 0;
73
n->status &= ~VIRTIO_NET_S_ANNOUNCE;
74
75
/* Flush any MAC and VLAN filter table state */
76
@@ -XXX,XX +XXX,XX @@ static int virtio_net_handle_vlan_table(VirtIONet *n, uint8_t cmd,
77
static int virtio_net_handle_announce(VirtIONet *n, uint8_t cmd,
78
struct iovec *iov, unsigned int iov_cnt)
79
{
80
+ trace_virtio_net_handle_announce(n->announce_timer.round);
81
if (cmd == VIRTIO_NET_CTRL_ANNOUNCE_ACK &&
82
n->status & VIRTIO_NET_S_ANNOUNCE) {
83
n->status &= ~VIRTIO_NET_S_ANNOUNCE;
84
- if (n->announce_counter) {
85
- timer_mod(n->announce_timer,
86
- qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
87
- self_announce_delay(n->announce_counter));
88
+ if (n->announce_timer.round) {
89
+ qemu_announce_timer_step(&n->announce_timer);
90
}
91
return VIRTIO_NET_OK;
92
} else {
93
@@ -XXX,XX +XXX,XX @@ static int virtio_net_post_load_device(void *opaque, int version_id)
94
VirtIODevice *vdev = VIRTIO_DEVICE(n);
95
int i, link_down;
96
97
+ trace_virtio_net_post_load_device();
98
virtio_net_set_mrg_rx_bufs(n, n->mergeable_rx_bufs,
99
virtio_vdev_has_feature(vdev,
100
VIRTIO_F_VERSION_1));
101
@@ -XXX,XX +XXX,XX @@ static int virtio_net_post_load_device(void *opaque, int version_id)
102
103
if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_GUEST_ANNOUNCE) &&
104
virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) {
105
- n->announce_counter = SELF_ANNOUNCE_ROUNDS;
106
- timer_mod(n->announce_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL));
107
+ qemu_announce_timer_reset(&n->announce_timer, migrate_announce_params(),
108
+ QEMU_CLOCK_VIRTUAL,
109
+ virtio_net_announce_timer, n);
110
+ if (n->announce_timer.round) {
111
+ timer_mod(n->announce_timer.tm,
112
+ qemu_clock_get_ms(n->announce_timer.type));
113
+ } else {
114
+ qemu_announce_timer_del(&n->announce_timer);
115
+ }
20
}
116
}
21
117
22
- fcntl(fd, F_SETFL, O_NONBLOCK);
118
return 0;
23
+ qemu_set_nonblock(fd);
119
@@ -XXX,XX +XXX,XX @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
24
vnet_hdr = tap_probe_vnet_hdr(fd);
120
qemu_macaddr_default_if_unset(&n->nic_conf.macaddr);
25
s = net_tap_fd_init(peer, "bridge", name, fd, vnet_hdr);
121
memcpy(&n->mac[0], &n->nic_conf.macaddr, sizeof(n->mac));
26
122
n->status = VIRTIO_NET_S_LINK_UP;
27
@@ -XXX,XX +XXX,XX @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
123
- n->announce_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL,
28
}
124
- virtio_net_announce_timer, n);
29
return;
125
+ qemu_announce_timer_reset(&n->announce_timer, migrate_announce_params(),
30
}
126
+ QEMU_CLOCK_VIRTUAL,
31
- fcntl(vhostfd, F_SETFL, O_NONBLOCK);
127
+ virtio_net_announce_timer, n);
32
+ qemu_set_nonblock(vhostfd);
128
33
}
129
if (n->netclient_type) {
34
options.opaque = (void *)(uintptr_t)vhostfd;
130
/*
35
131
@@ -XXX,XX +XXX,XX @@ static void virtio_net_device_unrealize(DeviceState *dev, Error **errp)
36
@@ -XXX,XX +XXX,XX @@ int net_init_tap(const Netdev *netdev, const char *name,
132
virtio_net_del_queue(n, i);
37
return -1;
133
}
38
}
134
39
135
- timer_del(n->announce_timer);
40
- fcntl(fd, F_SETFL, O_NONBLOCK);
136
- timer_free(n->announce_timer);
41
+ qemu_set_nonblock(fd);
137
+ qemu_announce_timer_del(&n->announce_timer);
42
138
g_free(n->vqs);
43
vnet_hdr = tap_probe_vnet_hdr(fd);
139
qemu_del_nic(n->nic);
44
140
virtio_net_rsc_cleanup(n);
45
@@ -XXX,XX +XXX,XX @@ int net_init_tap(const Netdev *netdev, const char *name,
141
diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
46
goto free_fail;
142
index XXXXXXX..XXXXXXX 100644
47
}
143
--- a/include/hw/virtio/virtio-net.h
48
144
+++ b/include/hw/virtio/virtio-net.h
49
- fcntl(fd, F_SETFL, O_NONBLOCK);
145
@@ -XXX,XX +XXX,XX @@
50
+ qemu_set_nonblock(fd);
146
#include "qemu/units.h"
51
147
#include "standard-headers/linux/virtio_net.h"
52
if (i == 0) {
148
#include "hw/virtio/virtio.h"
53
vnet_hdr = tap_probe_vnet_hdr(fd);
149
+#include "net/announce.h"
54
@@ -XXX,XX +XXX,XX @@ free_fail:
150
55
return -1;
151
#define TYPE_VIRTIO_NET "virtio-net-device"
56
}
152
#define VIRTIO_NET(obj) \
57
153
@@ -XXX,XX +XXX,XX @@ struct VirtIONet {
58
- fcntl(fd, F_SETFL, O_NONBLOCK);
154
char *netclient_name;
59
+ qemu_set_nonblock(fd);
155
char *netclient_type;
60
vnet_hdr = tap_probe_vnet_hdr(fd);
156
uint64_t curr_guest_offloads;
61
157
- QEMUTimer *announce_timer;
62
net_init_tap_one(tap, peer, "bridge", name, ifname,
158
- int announce_counter;
159
+ AnnounceTimer announce_timer;
160
bool needs_vnet_hdr_swap;
161
bool mtu_bypass_backend;
162
};
63
--
163
--
64
2.5.0
164
2.5.0
65
165
66
166
diff view generated by jsdifflib
New patch
1
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
2
3
Switch the announcements to using the new announce timer.
4
Move the code that does it to announce.c rather than savevm
5
because it really has nothing to do with the actual migration.
6
7
Migration starts the announce from bh's and so they're all
8
in the main thread/bql, and so there's never any racing with
9
the timers themselves.
10
11
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
12
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
13
Signed-off-by: Jason Wang <jasowang@redhat.com>
14
---
15
include/migration/misc.h | 10 -------
16
include/net/announce.h | 2 ++
17
include/sysemu/sysemu.h | 2 --
18
migration/migration.c | 2 +-
19
migration/migration.h | 4 +++
20
migration/savevm.c | 72 ++----------------------------------------------
21
migration/trace-events | 1 -
22
net/announce.c | 68 +++++++++++++++++++++++++++++++++++++++++++++
23
net/trace-events | 3 ++
24
9 files changed, 81 insertions(+), 83 deletions(-)
25
26
diff --git a/include/migration/misc.h b/include/migration/misc.h
27
index XXXXXXX..XXXXXXX 100644
28
--- a/include/migration/misc.h
29
+++ b/include/migration/misc.h
30
@@ -XXX,XX +XXX,XX @@ void blk_mig_init(void);
31
static inline void blk_mig_init(void) {}
32
#endif
33
34
-#define SELF_ANNOUNCE_ROUNDS 5
35
-
36
-static inline
37
-int64_t self_announce_delay(int round)
38
-{
39
- assert(round < SELF_ANNOUNCE_ROUNDS && round > 0);
40
- /* delay 50ms, 150ms, 250ms, ... */
41
- return 50 + (SELF_ANNOUNCE_ROUNDS - round - 1) * 100;
42
-}
43
-
44
AnnounceParameters *migrate_announce_params(void);
45
/* migration/savevm.c */
46
47
diff --git a/include/net/announce.h b/include/net/announce.h
48
index XXXXXXX..XXXXXXX 100644
49
--- a/include/net/announce.h
50
+++ b/include/net/announce.h
51
@@ -XXX,XX +XXX,XX @@ void qemu_announce_timer_reset(AnnounceTimer *timer,
52
QEMUTimerCB *cb,
53
void *opaque);
54
55
+void qemu_announce_self(AnnounceTimer *timer, AnnounceParameters *params);
56
+
57
#endif
58
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
59
index XXXXXXX..XXXXXXX 100644
60
--- a/include/sysemu/sysemu.h
61
+++ b/include/sysemu/sysemu.h
62
@@ -XXX,XX +XXX,XX @@ extern bool machine_init_done;
63
void qemu_add_machine_init_done_notifier(Notifier *notify);
64
void qemu_remove_machine_init_done_notifier(Notifier *notify);
65
66
-void qemu_announce_self(void);
67
-
68
extern int autostart;
69
70
typedef enum {
71
diff --git a/migration/migration.c b/migration/migration.c
72
index XXXXXXX..XXXXXXX 100644
73
--- a/migration/migration.c
74
+++ b/migration/migration.c
75
@@ -XXX,XX +XXX,XX @@ static void process_incoming_migration_bh(void *opaque)
76
* This must happen after all error conditions are dealt with and
77
* we're sure the VM is going to be running on this host.
78
*/
79
- qemu_announce_self();
80
+ qemu_announce_self(&mis->announce_timer, migrate_announce_params());
81
82
if (multifd_load_cleanup(&local_err) != 0) {
83
error_report_err(local_err);
84
diff --git a/migration/migration.h b/migration/migration.h
85
index XXXXXXX..XXXXXXX 100644
86
--- a/migration/migration.h
87
+++ b/migration/migration.h
88
@@ -XXX,XX +XXX,XX @@
89
#include "qemu/coroutine_int.h"
90
#include "hw/qdev.h"
91
#include "io/channel.h"
92
+#include "net/announce.h"
93
94
struct PostcopyBlocktimeContext;
95
96
@@ -XXX,XX +XXX,XX @@ struct MigrationIncomingState {
97
*/
98
QemuEvent main_thread_load_event;
99
100
+ /* For network announces */
101
+ AnnounceTimer announce_timer;
102
+
103
size_t largest_page_size;
104
bool have_fault_thread;
105
QemuThread fault_thread;
106
diff --git a/migration/savevm.c b/migration/savevm.c
107
index XXXXXXX..XXXXXXX 100644
108
--- a/migration/savevm.c
109
+++ b/migration/savevm.c
110
@@ -XXX,XX +XXX,XX @@
111
#include "sysemu/replay.h"
112
#include "qjson.h"
113
#include "migration/colo.h"
114
-
115
-#ifndef ETH_P_RARP
116
-#define ETH_P_RARP 0x8035
117
-#endif
118
-#define ARP_HTYPE_ETH 0x0001
119
-#define ARP_PTYPE_IP 0x0800
120
-#define ARP_OP_REQUEST_REV 0x3
121
+#include "net/announce.h"
122
123
const unsigned int postcopy_ram_discard_version = 0;
124
125
@@ -XXX,XX +XXX,XX @@ static struct mig_cmd_args {
126
* generic extendable format with an exception for two old entities.
127
*/
128
129
-static int announce_self_create(uint8_t *buf,
130
- uint8_t *mac_addr)
131
-{
132
- /* Ethernet header. */
133
- memset(buf, 0xff, 6); /* destination MAC addr */
134
- memcpy(buf + 6, mac_addr, 6); /* source MAC addr */
135
- *(uint16_t *)(buf + 12) = htons(ETH_P_RARP); /* ethertype */
136
-
137
- /* RARP header. */
138
- *(uint16_t *)(buf + 14) = htons(ARP_HTYPE_ETH); /* hardware addr space */
139
- *(uint16_t *)(buf + 16) = htons(ARP_PTYPE_IP); /* protocol addr space */
140
- *(buf + 18) = 6; /* hardware addr length (ethernet) */
141
- *(buf + 19) = 4; /* protocol addr length (IPv4) */
142
- *(uint16_t *)(buf + 20) = htons(ARP_OP_REQUEST_REV); /* opcode */
143
- memcpy(buf + 22, mac_addr, 6); /* source hw addr */
144
- memset(buf + 28, 0x00, 4); /* source protocol addr */
145
- memcpy(buf + 32, mac_addr, 6); /* target hw addr */
146
- memset(buf + 38, 0x00, 4); /* target protocol addr */
147
-
148
- /* Padding to get up to 60 bytes (ethernet min packet size, minus FCS). */
149
- memset(buf + 42, 0x00, 18);
150
-
151
- return 60; /* len (FCS will be added by hardware) */
152
-}
153
-
154
-static void qemu_announce_self_iter(NICState *nic, void *opaque)
155
-{
156
- uint8_t buf[60];
157
- int len;
158
-
159
- trace_qemu_announce_self_iter(qemu_ether_ntoa(&nic->conf->macaddr));
160
- len = announce_self_create(buf, nic->conf->macaddr.a);
161
-
162
- qemu_send_packet_raw(qemu_get_queue(nic), buf, len);
163
-}
164
-
165
-
166
-static void qemu_announce_self_once(void *opaque)
167
-{
168
- static int count = SELF_ANNOUNCE_ROUNDS;
169
- QEMUTimer *timer = *(QEMUTimer **)opaque;
170
-
171
- qemu_foreach_nic(qemu_announce_self_iter, NULL);
172
-
173
- if (--count) {
174
- /* delay 50ms, 150ms, 250ms, ... */
175
- timer_mod(timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) +
176
- self_announce_delay(count));
177
- } else {
178
- timer_del(timer);
179
- timer_free(timer);
180
- }
181
-}
182
-
183
-void qemu_announce_self(void)
184
-{
185
- static QEMUTimer *timer;
186
- timer = timer_new_ms(QEMU_CLOCK_REALTIME, qemu_announce_self_once, &timer);
187
- qemu_announce_self_once(&timer);
188
-}
189
-
190
/***********************************************************/
191
/* savevm/loadvm support */
192
193
@@ -XXX,XX +XXX,XX @@ static void loadvm_postcopy_handle_run_bh(void *opaque)
194
{
195
Error *local_err = NULL;
196
HandleRunBhData *data = opaque;
197
+ MigrationIncomingState *mis = migration_incoming_get_current();
198
199
/* TODO we should move all of this lot into postcopy_ram.c or a shared code
200
* in migration.c
201
*/
202
cpu_synchronize_all_post_init();
203
204
- qemu_announce_self();
205
+ qemu_announce_self(&mis->announce_timer, migrate_announce_params());
206
207
/* Make sure all file formats flush their mutable metadata.
208
* If we get an error here, just don't restart the VM yet. */
209
diff --git a/migration/trace-events b/migration/trace-events
210
index XXXXXXX..XXXXXXX 100644
211
--- a/migration/trace-events
212
+++ b/migration/trace-events
213
@@ -XXX,XX +XXX,XX @@ vmstate_save_state_top(const char *idstr) "%s"
214
vmstate_subsection_save_loop(const char *name, const char *sub) "%s/%s"
215
vmstate_subsection_save_top(const char *idstr) "%s"
216
vmstate_load(const char *idstr, const char *vmsd_name) "%s, %s"
217
-qemu_announce_self_iter(const char *mac) "%s"
218
219
# migration/vmstate.c
220
vmstate_load_field_error(const char *field, int ret) "field \"%s\" load failed, ret = %d"
221
diff --git a/net/announce.c b/net/announce.c
222
index XXXXXXX..XXXXXXX 100644
223
--- a/net/announce.c
224
+++ b/net/announce.c
225
@@ -XXX,XX +XXX,XX @@
226
#include "qemu/osdep.h"
227
#include "qemu-common.h"
228
#include "net/announce.h"
229
+#include "net/net.h"
230
#include "qapi/clone-visitor.h"
231
#include "qapi/qapi-visit-net.h"
232
+#include "trace.h"
233
234
int64_t qemu_announce_timer_step(AnnounceTimer *timer)
235
{
236
@@ -XXX,XX +XXX,XX @@ void qemu_announce_timer_reset(AnnounceTimer *timer,
237
timer->type = type;
238
timer->tm = timer_new_ms(type, cb, opaque);
239
}
240
+
241
+#ifndef ETH_P_RARP
242
+#define ETH_P_RARP 0x8035
243
+#endif
244
+#define ARP_HTYPE_ETH 0x0001
245
+#define ARP_PTYPE_IP 0x0800
246
+#define ARP_OP_REQUEST_REV 0x3
247
+
248
+static int announce_self_create(uint8_t *buf,
249
+ uint8_t *mac_addr)
250
+{
251
+ /* Ethernet header. */
252
+ memset(buf, 0xff, 6); /* destination MAC addr */
253
+ memcpy(buf + 6, mac_addr, 6); /* source MAC addr */
254
+ *(uint16_t *)(buf + 12) = htons(ETH_P_RARP); /* ethertype */
255
+
256
+ /* RARP header. */
257
+ *(uint16_t *)(buf + 14) = htons(ARP_HTYPE_ETH); /* hardware addr space */
258
+ *(uint16_t *)(buf + 16) = htons(ARP_PTYPE_IP); /* protocol addr space */
259
+ *(buf + 18) = 6; /* hardware addr length (ethernet) */
260
+ *(buf + 19) = 4; /* protocol addr length (IPv4) */
261
+ *(uint16_t *)(buf + 20) = htons(ARP_OP_REQUEST_REV); /* opcode */
262
+ memcpy(buf + 22, mac_addr, 6); /* source hw addr */
263
+ memset(buf + 28, 0x00, 4); /* source protocol addr */
264
+ memcpy(buf + 32, mac_addr, 6); /* target hw addr */
265
+ memset(buf + 38, 0x00, 4); /* target protocol addr */
266
+
267
+ /* Padding to get up to 60 bytes (ethernet min packet size, minus FCS). */
268
+ memset(buf + 42, 0x00, 18);
269
+
270
+ return 60; /* len (FCS will be added by hardware) */
271
+}
272
+
273
+static void qemu_announce_self_iter(NICState *nic, void *opaque)
274
+{
275
+ uint8_t buf[60];
276
+ int len;
277
+
278
+ trace_qemu_announce_self_iter(qemu_ether_ntoa(&nic->conf->macaddr));
279
+ len = announce_self_create(buf, nic->conf->macaddr.a);
280
+
281
+ qemu_send_packet_raw(qemu_get_queue(nic), buf, len);
282
+}
283
+static void qemu_announce_self_once(void *opaque)
284
+{
285
+ AnnounceTimer *timer = (AnnounceTimer *)opaque;
286
+
287
+ qemu_foreach_nic(qemu_announce_self_iter, NULL);
288
+
289
+ if (--timer->round) {
290
+ qemu_announce_timer_step(timer);
291
+ } else {
292
+ qemu_announce_timer_del(timer);
293
+ }
294
+}
295
+
296
+void qemu_announce_self(AnnounceTimer *timer, AnnounceParameters *params)
297
+{
298
+ qemu_announce_timer_reset(timer, params, QEMU_CLOCK_REALTIME,
299
+ qemu_announce_self_once, timer);
300
+ if (params->rounds) {
301
+ qemu_announce_self_once(timer);
302
+ } else {
303
+ qemu_announce_timer_del(timer);
304
+ }
305
+}
306
diff --git a/net/trace-events b/net/trace-events
307
index XXXXXXX..XXXXXXX 100644
308
--- a/net/trace-events
309
+++ b/net/trace-events
310
@@ -XXX,XX +XXX,XX @@
311
# See docs/devel/tracing.txt for syntax documentation.
312
313
+# net/announce.c
314
+qemu_announce_self_iter(const char *mac) "%s"
315
+
316
# net/vhost-user.c
317
vhost_user_event(const char *chr, int event) "chr: %s got event: %d"
318
319
--
320
2.5.0
321
322
diff view generated by jsdifflib
New patch
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
1
2
3
Some network devices have a capability to do self announcements
4
(ex: virtio-net). Add infrastructure that would allow devices
5
to expose this ability.
6
7
Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
8
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
9
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
---
12
include/net/net.h | 2 ++
13
net/announce.c | 5 +++++
14
2 files changed, 7 insertions(+)
15
16
diff --git a/include/net/net.h b/include/net/net.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/net/net.h
19
+++ b/include/net/net.h
20
@@ -XXX,XX +XXX,XX @@ typedef int (SetVnetLE)(NetClientState *, bool);
21
typedef int (SetVnetBE)(NetClientState *, bool);
22
typedef struct SocketReadState SocketReadState;
23
typedef void (SocketReadStateFinalize)(SocketReadState *rs);
24
+typedef void (NetAnnounce)(NetClientState *);
25
26
typedef struct NetClientInfo {
27
NetClientDriver type;
28
@@ -XXX,XX +XXX,XX @@ typedef struct NetClientInfo {
29
SetVnetHdrLen *set_vnet_hdr_len;
30
SetVnetLE *set_vnet_le;
31
SetVnetBE *set_vnet_be;
32
+ NetAnnounce *announce;
33
} NetClientInfo;
34
35
struct NetClientState {
36
diff --git a/net/announce.c b/net/announce.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/net/announce.c
39
+++ b/net/announce.c
40
@@ -XXX,XX +XXX,XX @@ static void qemu_announce_self_iter(NICState *nic, void *opaque)
41
len = announce_self_create(buf, nic->conf->macaddr.a);
42
43
qemu_send_packet_raw(qemu_get_queue(nic), buf, len);
44
+
45
+ /* if the NIC provides it's own announcement support, use it as well */
46
+ if (nic->ncs->info->announce) {
47
+ nic->ncs->info->announce(nic->ncs);
48
+ }
49
}
50
static void qemu_announce_self_once(void *opaque)
51
{
52
--
53
2.5.0
54
55
diff view generated by jsdifflib
1
From: yuchenlin <yuchenlin@synology.com>
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
2
2
3
Due to too early RCT0 interrput, win10x32 may hang on booting.
3
Expose the virtio-net self announcement capability and allow
4
This problem can be reproduced by doing power cycle on win10x32 guest.
4
qemu_announce_self() to call it.
5
In our environment, we have 10 win10x32 and stress power cycle.
6
The problem will happen about 20 rounds.
7
5
8
Below shows some log with comment:
6
These announces are caused by something external (i.e. the
7
announce-self command); they won't trigger if the migration
8
counter is triggering announces at the same time.
9
9
10
The normal case:
10
Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
11
11
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
12
22831@1551928392.984687:e1000x_rx_disabled Received packet dropped
12
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
13
because receive is disabled RCTL = 0
14
22831@1551928392.985655:e1000x_rx_disabled Received packet dropped
15
because receive is disabled RCTL = 0
16
22831@1551928392.985801:e1000x_rx_disabled Received packet dropped
17
because receive is disabled RCTL = 0
18
e1000: set_ics 0, ICR 0, IMR 0
19
e1000: set_ics 0, ICR 0, IMR 0
20
e1000: set_ics 0, ICR 0, IMR 0
21
e1000: RCTL: 0, mac_reg[RCTL] = 0x0
22
22831@1551928393.056710:e1000x_rx_disabled Received packet dropped
23
because receive is disabled RCTL = 0
24
e1000: set_ics 0, ICR 0, IMR 0
25
e1000: ICR read: 0
26
e1000: set_ics 0, ICR 0, IMR 0
27
e1000: set_ics 0, ICR 0, IMR 0
28
e1000: RCTL: 0, mac_reg[RCTL] = 0x0
29
22831@1551928393.077548:e1000x_rx_disabled Received packet dropped
30
because receive is disabled RCTL = 0
31
e1000: set_ics 0, ICR 0, IMR 0
32
e1000: ICR read: 0
33
e1000: set_ics 2, ICR 0, IMR 0
34
e1000: set_ics 2, ICR 2, IMR 0
35
e1000: RCTL: 0, mac_reg[RCTL] = 0x0
36
22831@1551928393.102974:e1000x_rx_disabled Received packet dropped
37
because receive is disabled RCTL = 0
38
22831@1551928393.103267:e1000x_rx_disabled Received packet dropped
39
because receive is disabled RCTL = 0
40
e1000: RCTL: 255, mac_reg[RCTL] = 0x40002 <- win10x32 says it can handle
41
RX now
42
e1000: set_ics 0, ICR 2, IMR 9d <- unmask interrupt
43
e1000: RCTL: 255, mac_reg[RCTL] = 0x48002
44
e1000: set_ics 80, ICR 2, IMR 9d <- interrupt and work!
45
...
46
47
The bad case:
48
49
27744@1551930483.117766:e1000x_rx_disabled Received packet dropped
50
because receive is disabled RCTL = 0
51
27744@1551930483.118398:e1000x_rx_disabled Received packet dropped
52
because receive is disabled RCTL = 0
53
e1000: set_ics 0, ICR 0, IMR 0
54
e1000: set_ics 0, ICR 0, IMR 0
55
e1000: set_ics 0, ICR 0, IMR 0
56
e1000: RCTL: 0, mac_reg[RCTL] = 0x0
57
27744@1551930483.198063:e1000x_rx_disabled Received packet dropped
58
because receive is disabled RCTL = 0
59
e1000: set_ics 0, ICR 0, IMR 0
60
e1000: ICR read: 0
61
e1000: set_ics 0, ICR 0, IMR 0
62
e1000: set_ics 0, ICR 0, IMR 0
63
e1000: RCTL: 0, mac_reg[RCTL] = 0x0
64
27744@1551930483.218675:e1000x_rx_disabled Received packet dropped
65
because receive is disabled RCTL = 0
66
e1000: set_ics 0, ICR 0, IMR 0
67
e1000: ICR read: 0
68
e1000: set_ics 2, ICR 0, IMR 0
69
e1000: set_ics 2, ICR 2, IMR 0
70
e1000: RCTL: 0, mac_reg[RCTL] = 0x0
71
27744@1551930483.241768:e1000x_rx_disabled Received packet dropped
72
because receive is disabled RCTL = 0
73
27744@1551930483.241979:e1000x_rx_disabled Received packet dropped
74
because receive is disabled RCTL = 0
75
e1000: RCTL: 255, mac_reg[RCTL] = 0x40002 <- win10x32 says it can handle
76
RX now
77
e1000: set_ics 80, ICR 2, IMR 0 <- flush queue (caused by setting RCTL)
78
e1000: set_ics 0, ICR 82, IMR 9d <- unmask interrupt and because 0x82&0x9d
79
!= 0 generate interrupt, hang on here...
80
81
To workaround this problem, simply delay flush queue. Also stop receiving
82
when timer is going to run.
83
84
Tested on CentOS, Win7SP1x64 and Win10x32.
85
86
Signed-off-by: yuchenlin <yuchenlin@synology.com>
87
Reviewed-by: Dmitry Fleytman <dmitry.fleytman@gmail.com>
88
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
Signed-off-by: Jason Wang <jasowang@redhat.com>
89
---
14
---
90
hw/net/e1000.c | 24 ++++++++++++++++++++++--
15
hw/net/trace-events | 1 +
91
1 file changed, 22 insertions(+), 2 deletions(-)
16
hw/net/virtio-net.c | 35 ++++++++++++++++++++++++++++++++---
17
2 files changed, 33 insertions(+), 3 deletions(-)
92
18
93
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
19
diff --git a/hw/net/trace-events b/hw/net/trace-events
94
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
95
--- a/hw/net/e1000.c
21
--- a/hw/net/trace-events
96
+++ b/hw/net/e1000.c
22
+++ b/hw/net/trace-events
97
@@ -XXX,XX +XXX,XX @@ typedef struct E1000State_st {
23
@@ -XXX,XX +XXX,XX @@ sunhme_rx_desc(uint32_t addr, int offset, uint32_t status, int len, int cr, int
98
bool mit_irq_level; /* Tracks interrupt pin level. */
24
sunhme_rx_xsum_calc(uint16_t xsum) "calculated incoming xsum as 0x%x"
99
uint32_t mit_ide; /* Tracks E1000_TXD_CMD_IDE bit. */
25
100
26
# hw/net/virtio-net.c
101
+ QEMUTimer *flush_queue_timer;
27
+virtio_net_announce_notify(void) ""
28
virtio_net_announce_timer(int round) "%d"
29
virtio_net_handle_announce(int round) "%d"
30
virtio_net_post_load_device(void)
31
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/hw/net/virtio-net.c
34
+++ b/hw/net/virtio-net.c
35
@@ -XXX,XX +XXX,XX @@ static bool virtio_net_started(VirtIONet *n, uint8_t status)
36
(n->status & VIRTIO_NET_S_LINK_UP) && vdev->vm_running;
37
}
38
39
+static void virtio_net_announce_notify(VirtIONet *net)
40
+{
41
+ VirtIODevice *vdev = VIRTIO_DEVICE(net);
42
+ trace_virtio_net_announce_notify();
102
+
43
+
103
/* Compatibility flags for migration to/from qemu 1.3.0 and older */
44
+ net->status |= VIRTIO_NET_S_ANNOUNCE;
104
#define E1000_FLAG_AUTONEG_BIT 0
45
+ virtio_notify_config(vdev);
105
#define E1000_FLAG_MIT_BIT 1
106
@@ -XXX,XX +XXX,XX @@ static void e1000_reset(void *opaque)
107
108
timer_del(d->autoneg_timer);
109
timer_del(d->mit_timer);
110
+ timer_del(d->flush_queue_timer);
111
d->mit_timer_on = 0;
112
d->mit_irq_level = 0;
113
d->mit_ide = 0;
114
@@ -XXX,XX +XXX,XX @@ set_ctrl(E1000State *s, int index, uint32_t val)
115
}
116
117
static void
118
+e1000_flush_queue_timer(void *opaque)
119
+{
120
+ E1000State *s = opaque;
121
+
122
+ qemu_flush_queued_packets(qemu_get_queue(s->nic));
123
+}
46
+}
124
+
47
+
125
+static void
48
static void virtio_net_announce_timer(void *opaque)
126
set_rx_control(E1000State *s, int index, uint32_t val)
127
{
49
{
128
s->mac_reg[RCTL] = val;
50
VirtIONet *n = opaque;
129
@@ -XXX,XX +XXX,XX @@ set_rx_control(E1000State *s, int index, uint32_t val)
51
- VirtIODevice *vdev = VIRTIO_DEVICE(n);
130
s->rxbuf_min_shift = ((val / E1000_RCTL_RDMTS_QUAT) & 3) + 1;
52
trace_virtio_net_announce_timer(n->announce_timer.round);
131
DBGOUT(RX, "RCTL: %d, mac_reg[RCTL] = 0x%x\n", s->mac_reg[RDT],
53
132
s->mac_reg[RCTL]);
54
n->announce_timer.round--;
133
- qemu_flush_queued_packets(qemu_get_queue(s->nic));
55
- n->status |= VIRTIO_NET_S_ANNOUNCE;
134
+ timer_mod(s->flush_queue_timer,
56
- virtio_notify_config(vdev);
135
+ qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000);
57
+ virtio_net_announce_notify(n);
136
}
58
+}
137
59
+
138
static void
60
+static void virtio_net_announce(NetClientState *nc)
139
@@ -XXX,XX +XXX,XX @@ e1000_can_receive(NetClientState *nc)
61
+{
140
E1000State *s = qemu_get_nic_opaque(nc);
62
+ VirtIONet *n = qemu_get_nic_opaque(nc);
141
63
+ VirtIODevice *vdev = VIRTIO_DEVICE(n);
142
return e1000x_rx_ready(&s->parent_obj, s->mac_reg) &&
64
+
143
- e1000_has_rxbufs(s, 1);
65
+ /*
144
+ e1000_has_rxbufs(s, 1) && !timer_pending(s->flush_queue_timer);
66
+ * Make sure the virtio migration announcement timer isn't running
145
}
67
+ * If it is, let it trigger announcement so that we do not cause
146
68
+ * confusion.
147
static uint64_t rx_desc_base(E1000State *s)
69
+ */
148
@@ -XXX,XX +XXX,XX @@ e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt)
70
+ if (n->announce_timer.round) {
149
return -1;
71
+ return;
150
}
151
152
+ if (timer_pending(s->flush_queue_timer)) {
153
+ return 0;
154
+ }
72
+ }
155
+
73
+
156
/* Pad to minimum Ethernet frame length */
74
+ if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_GUEST_ANNOUNCE) &&
157
if (size < sizeof(min_buf)) {
75
+ virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) {
158
iov_to_buf(iov, iovcnt, 0, min_buf, size);
76
+ virtio_net_announce_notify(n);
159
@@ -XXX,XX +XXX,XX @@ pci_e1000_uninit(PCIDevice *dev)
77
+ }
160
timer_free(d->autoneg_timer);
161
timer_del(d->mit_timer);
162
timer_free(d->mit_timer);
163
+ timer_del(d->flush_queue_timer);
164
+ timer_free(d->flush_queue_timer);
165
qemu_del_nic(d->nic);
166
}
78
}
167
79
168
@@ -XXX,XX +XXX,XX @@ static void pci_e1000_realize(PCIDevice *pci_dev, Error **errp)
80
static void virtio_net_vhost_status(VirtIONet *n, uint8_t status)
169
81
@@ -XXX,XX +XXX,XX @@ static NetClientInfo net_virtio_info = {
170
d->autoneg_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, e1000_autoneg_timer, d);
82
.receive = virtio_net_receive,
171
d->mit_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, e1000_mit_timer, d);
83
.link_status_changed = virtio_net_set_link_status,
172
+ d->flush_queue_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL,
84
.query_rx_filter = virtio_net_query_rxfilter,
173
+ e1000_flush_queue_timer, d);
85
+ .announce = virtio_net_announce,
174
}
86
};
175
87
176
static void qdev_e1000_reset(DeviceState *dev)
88
static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx)
89
@@ -XXX,XX +XXX,XX @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
90
qemu_announce_timer_reset(&n->announce_timer, migrate_announce_params(),
91
QEMU_CLOCK_VIRTUAL,
92
virtio_net_announce_timer, n);
93
+ n->announce_timer.round = 0;
94
95
if (n->netclient_type) {
96
/*
177
--
97
--
178
2.5.0
98
2.5.0
179
99
180
100
diff view generated by jsdifflib
New patch
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
1
2
3
Add a qmp command that can trigger guest announcements.
4
5
It uses its own announce-timer instance, and parameters
6
passed to it explicitly in the command.
7
8
Like most qmp commands, it's in the main thread/bql, so
9
there's no racing with any outstanding timer.
10
11
Based on work of Germano Veit Michel <germano@redhat.com> and
12
Vladislav Yasevich <vyasevic@redhat.com>
13
14
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
15
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
16
Signed-off-by: Jason Wang <jasowang@redhat.com>
17
---
18
net/announce.c | 7 +++++++
19
qapi/net.json | 20 ++++++++++++++++++++
20
2 files changed, 27 insertions(+)
21
22
diff --git a/net/announce.c b/net/announce.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/net/announce.c
25
+++ b/net/announce.c
26
@@ -XXX,XX +XXX,XX @@
27
#include "net/net.h"
28
#include "qapi/clone-visitor.h"
29
#include "qapi/qapi-visit-net.h"
30
+#include "qapi/qapi-commands-net.h"
31
#include "trace.h"
32
33
int64_t qemu_announce_timer_step(AnnounceTimer *timer)
34
@@ -XXX,XX +XXX,XX @@ void qemu_announce_self(AnnounceTimer *timer, AnnounceParameters *params)
35
qemu_announce_timer_del(timer);
36
}
37
}
38
+
39
+void qmp_announce_self(AnnounceParameters *params, Error **errp)
40
+{
41
+ static AnnounceTimer announce_timer;
42
+ qemu_announce_self(&announce_timer, params);
43
+}
44
diff --git a/qapi/net.json b/qapi/net.json
45
index XXXXXXX..XXXXXXX 100644
46
--- a/qapi/net.json
47
+++ b/qapi/net.json
48
@@ -XXX,XX +XXX,XX @@
49
'max': 'int',
50
'rounds': 'int',
51
'step': 'int' } }
52
+
53
+##
54
+# @announce-self:
55
+#
56
+# Trigger generation of broadcast RARP frames to update network switches.
57
+# This can be useful when network bonds fail-over the active slave.
58
+#
59
+# @params: AnnounceParameters giving timing and repetition count of announce
60
+#
61
+# Example:
62
+#
63
+# -> { "execute": "announce-self"
64
+# "arguments": {
65
+# "initial": 50, "max": 550, "rounds": 10, "step": 50 } }
66
+# <- { "return": {} }
67
+#
68
+# Since: 4.0
69
+##
70
+{ 'command': 'announce-self', 'boxed': true,
71
+ 'data' : 'AnnounceParameters'}
72
--
73
2.5.0
74
75
diff view generated by jsdifflib
New patch
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
1
2
3
Add an HMP command to trigger self annocements.
4
Unlike the QMP command (which takes a set of parameters), the HMP
5
command reuses the set of parameters used for migration.
6
7
Signend-off-by: Vladislav Yasevich <vyasevic@redhat.com>
8
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
9
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
---
12
hmp-commands.hx | 16 ++++++++++++++++
13
hmp.c | 5 +++++
14
hmp.h | 1 +
15
tests/test-hmp.c | 1 +
16
4 files changed, 23 insertions(+)
17
18
diff --git a/hmp-commands.hx b/hmp-commands.hx
19
index XXXXXXX..XXXXXXX 100644
20
--- a/hmp-commands.hx
21
+++ b/hmp-commands.hx
22
@@ -XXX,XX +XXX,XX @@ stops because the size limit is reached.
23
ETEXI
24
25
{
26
+ .name = "announce_self",
27
+ .args_type = "",
28
+ .params = "",
29
+ .help = "Trigger GARP/RARP announcements",
30
+ .cmd = hmp_announce_self,
31
+ },
32
+
33
+STEXI
34
+@item announce_self
35
+@findex announce_self
36
+Trigger a round of GARP/RARP broadcasts; this is useful for explicitly updating the
37
+network infrastructure after a reconfiguration or some forms of migration.
38
+The timings of the round are set by the migration announce parameters.
39
+ETEXI
40
+
41
+ {
42
.name = "migrate",
43
.args_type = "detach:-d,blk:-b,inc:-i,resume:-r,uri:s",
44
.params = "[-d] [-b] [-i] [-r] uri",
45
diff --git a/hmp.c b/hmp.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/hmp.c
48
+++ b/hmp.c
49
@@ -XXX,XX +XXX,XX @@ void hmp_info_snapshots(Monitor *mon, const QDict *qdict)
50
51
}
52
53
+void hmp_announce_self(Monitor *mon, const QDict *qdict)
54
+{
55
+ qmp_announce_self(migrate_announce_params(), NULL);
56
+}
57
+
58
void hmp_migrate_cancel(Monitor *mon, const QDict *qdict)
59
{
60
qmp_migrate_cancel(NULL);
61
diff --git a/hmp.h b/hmp.h
62
index XXXXXXX..XXXXXXX 100644
63
--- a/hmp.h
64
+++ b/hmp.h
65
@@ -XXX,XX +XXX,XX @@ void hmp_sync_profile(Monitor *mon, const QDict *qdict);
66
void hmp_system_reset(Monitor *mon, const QDict *qdict);
67
void hmp_system_powerdown(Monitor *mon, const QDict *qdict);
68
void hmp_exit_preconfig(Monitor *mon, const QDict *qdict);
69
+void hmp_announce_self(Monitor *mon, const QDict *qdict);
70
void hmp_cpu(Monitor *mon, const QDict *qdict);
71
void hmp_memsave(Monitor *mon, const QDict *qdict);
72
void hmp_pmemsave(Monitor *mon, const QDict *qdict);
73
diff --git a/tests/test-hmp.c b/tests/test-hmp.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/tests/test-hmp.c
76
+++ b/tests/test-hmp.c
77
@@ -XXX,XX +XXX,XX @@
78
static int verbose;
79
80
static const char *hmp_cmds[] = {
81
+ "announce_self",
82
"boot_set ndc",
83
"chardev-add null,id=testchardev1",
84
"chardev-send-break testchardev1",
85
--
86
2.5.0
87
88
diff view generated by jsdifflib
1
From: Marc-André Lureau <marcandre.lureau@redhat.com>
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
2
2
3
-net socket has a fd argument, and may be passed pre-opened sockets.
3
We now expose qemu_announce_self through QMP and HMP. Add a test
4
with some very basic packet validation (make sure we get a RARP).
4
5
5
TCP sockets use framing.
6
Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
6
UDP sockets have datagram boundaries.
7
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
7
8
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
8
When given a unix dgram socket, it will be able to read from it, but
9
will attempt to send on the dgram_dst, which is unset. The other end
10
will not receive the data.
11
12
Let's teach -net socket to recognize a UNIX DGRAM socket, and use the
13
regular send() command (without dgram_dst).
14
15
This makes running slirp out-of-process possible that
16
way (python pseudo-code):
17
18
a, b = socket.socketpair(socket.AF_UNIX, socket.SOCK_DGRAM)
19
20
subprocess.Popen('qemu -net socket,fd=%d -net user' % a.fileno(), shell=True)
21
subprocess.Popen('qemu ... -net nic -net socket,fd=%d' % b.fileno(), shell=True)
22
23
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
24
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
25
---
10
---
26
net/socket.c | 25 +++++++++++++++++++++----
11
tests/Makefile.include | 3 ++
27
1 file changed, 21 insertions(+), 4 deletions(-)
12
tests/test-announce-self.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++
13
2 files changed, 85 insertions(+)
14
create mode 100644 tests/test-announce-self.c
28
15
29
diff --git a/net/socket.c b/net/socket.c
16
diff --git a/tests/Makefile.include b/tests/Makefile.include
30
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
31
--- a/net/socket.c
18
--- a/tests/Makefile.include
32
+++ b/net/socket.c
19
+++ b/tests/Makefile.include
33
@@ -XXX,XX +XXX,XX @@ static ssize_t net_socket_receive_dgram(NetClientState *nc, const uint8_t *buf,
20
@@ -XXX,XX +XXX,XX @@ check-qtest-i386-$(CONFIG_SLIRP) += tests/test-netfilter$(EXESUF)
34
ssize_t ret;
21
check-qtest-i386-$(CONFIG_POSIX) += tests/test-filter-mirror$(EXESUF)
35
22
check-qtest-i386-$(CONFIG_RTL8139_PCI) += tests/test-filter-redirector$(EXESUF)
36
do {
23
check-qtest-i386-y += tests/migration-test$(EXESUF)
37
- ret = qemu_sendto(s->fd, buf, size, 0,
24
+check-qtest-i386-y += tests/test-announce-self$(EXESUF)
38
- (struct sockaddr *)&s->dgram_dst,
25
check-qtest-i386-y += tests/test-x86-cpuid-compat$(EXESUF)
39
- sizeof(s->dgram_dst));
26
check-qtest-i386-y += tests/numa-test$(EXESUF)
40
+ if (s->dgram_dst.sin_family != AF_UNIX) {
27
check-qtest-x86_64-y += $(check-qtest-i386-y)
41
+ ret = qemu_sendto(s->fd, buf, size, 0,
28
@@ -XXX,XX +XXX,XX @@ check-qtest-ppc64-$(CONFIG_PSERIES) += tests/spapr-phb-test$(EXESUF)
42
+ (struct sockaddr *)&s->dgram_dst,
29
check-qtest-ppc64-$(CONFIG_PSERIES) += tests/device-plug-test$(EXESUF)
43
+ sizeof(s->dgram_dst));
30
check-qtest-ppc64-$(CONFIG_POWERNV) += tests/pnv-xscom-test$(EXESUF)
44
+ } else {
31
check-qtest-ppc64-y += tests/migration-test$(EXESUF)
45
+ ret = send(s->fd, buf, size, 0);
32
+check-qtest-ppc64-y += tests/test-announce-self$(EXESUF)
46
+ }
33
check-qtest-ppc64-$(CONFIG_PSERIES) += tests/rtas-test$(EXESUF)
47
} while (ret == -1 && errno == EINTR);
34
check-qtest-ppc64-$(CONFIG_SLIRP) += tests/pxe-test$(EXESUF)
48
35
check-qtest-ppc64-$(CONFIG_USB_OHCI) += tests/usb-hcd-ohci-test$(EXESUF)
49
if (ret == -1 && errno == EAGAIN) {
36
@@ -XXX,XX +XXX,XX @@ tests/usb-hcd-ehci-test$(EXESUF): tests/usb-hcd-ehci-test.o $(libqos-usb-obj-y)
50
@@ -XXX,XX +XXX,XX @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer,
37
tests/usb-hcd-xhci-test$(EXESUF): tests/usb-hcd-xhci-test.o $(libqos-usb-obj-y)
51
int newfd;
38
tests/cpu-plug-test$(EXESUF): tests/cpu-plug-test.o
52
NetClientState *nc;
39
tests/migration-test$(EXESUF): tests/migration-test.o
53
NetSocketState *s;
40
+tests/test-announce-self$(EXESUF): tests/test-announce-self.o
54
+ SocketAddress *sa;
41
tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o $(test-util-obj-y) \
55
+ SocketAddressType sa_type;
42
    $(qtest-obj-y) $(test-io-obj-y) $(libqos-virtio-obj-y) $(libqos-pc-obj-y) \
43
    $(chardev-obj-y)
44
diff --git a/tests/test-announce-self.c b/tests/test-announce-self.c
45
new file mode 100644
46
index XXXXXXX..XXXXXXX
47
--- /dev/null
48
+++ b/tests/test-announce-self.c
49
@@ -XXX,XX +XXX,XX @@
50
+/*
51
+ * QTest testcase for qemu_announce_self
52
+ *
53
+ * Copyright (c) 2017 Red hat, Inc.
54
+ * Copyright (c) 2014 SUSE LINUX Products GmbH
55
+ *
56
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
57
+ * See the COPYING file in the top-level directory.
58
+ */
56
+
59
+
57
+ sa = socket_local_address(fd, errp);
60
+#include "qemu/osdep.h"
58
+ if (!sa) {
61
+#include "libqtest.h"
59
+ return NULL;
62
+#include "qapi/qmp/qdict.h"
60
+ }
63
+#include "qemu-common.h"
61
+ sa_type = sa->type;
64
+#include "qemu/sockets.h"
62
+ qapi_free_SocketAddress(sa);
65
+#include "qemu/iov.h"
63
66
+#include "libqos/libqos-pc.h"
64
/* fd passed: multicast: "learn" dgram_dst address from bound address and save it
67
+#include "libqos/libqos-spapr.h"
65
* Because this may be "shared" socket from a "master" process, datagrams would be recv()
66
@@ -XXX,XX +XXX,XX @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer,
67
"socket: fd=%d (cloned mcast=%s:%d)",
68
fd, inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
69
} else {
70
+ if (sa_type == SOCKET_ADDRESS_TYPE_UNIX) {
71
+ s->dgram_dst.sin_family = AF_UNIX;
72
+ }
73
+
68
+
74
snprintf(nc->info_str, sizeof(nc->info_str),
69
+#ifndef ETH_P_RARP
75
- "socket: fd=%d", fd);
70
+#define ETH_P_RARP 0x8035
76
+ "socket: fd=%d %s", fd, SocketAddressType_str(sa_type));
71
+#endif
77
}
72
+
78
73
+static QTestState *test_init(int socket)
79
return s;
74
+{
75
+ char *args;
76
+
77
+ args = g_strdup_printf("-netdev socket,fd=%d,id=hs0 -device "
78
+ "virtio-net-pci,netdev=hs0", socket);
79
+
80
+ return qtest_start(args);
81
+}
82
+
83
+
84
+static void test_announce(int socket)
85
+{
86
+ char buffer[60];
87
+ int len;
88
+ QDict *rsp;
89
+ int ret;
90
+ uint16_t *proto = (uint16_t *)&buffer[12];
91
+
92
+ rsp = qmp("{ 'execute' : 'announce-self', "
93
+ " 'arguments': {"
94
+ " 'initial': 50, 'max': 550,"
95
+ " 'rounds': 10, 'step': 50 } }");
96
+ assert(!qdict_haskey(rsp, "error"));
97
+ qobject_unref(rsp);
98
+
99
+ /* Catch the packet and make sure it's a RARP */
100
+ ret = qemu_recv(socket, &len, sizeof(len), 0);
101
+ g_assert_cmpint(ret, ==, sizeof(len));
102
+ len = ntohl(len);
103
+
104
+ ret = qemu_recv(socket, buffer, len, 0);
105
+ g_assert_cmpint(*proto, ==, htons(ETH_P_RARP));
106
+}
107
+
108
+static void setup(gconstpointer data)
109
+{
110
+ QTestState *qs;
111
+ void (*func) (int socket) = data;
112
+ int sv[2], ret;
113
+
114
+ ret = socketpair(PF_UNIX, SOCK_STREAM, 0, sv);
115
+ g_assert_cmpint(ret, !=, -1);
116
+
117
+ qs = test_init(sv[1]);
118
+ func(sv[0]);
119
+
120
+ /* End test */
121
+ close(sv[0]);
122
+ qtest_quit(qs);
123
+}
124
+
125
+int main(int argc, char **argv)
126
+{
127
+ g_test_init(&argc, &argv, NULL);
128
+ qtest_add_data_func("/virtio/net/test_announce_self", test_announce, setup);
129
+
130
+ return g_test_run();
131
+}
80
--
132
--
81
2.5.0
133
2.5.0
82
134
83
135
diff view generated by jsdifflib