1
The following changes since commit f4abdf32714d1845b7c01ec136dd2b04c2f7db47:
1
The following changes since commit b6179aaff961627fcb59d7b234297966b81ac726:
2
2
3
Merge remote-tracking branch 'remotes/stsquad/tags/pull-testing-docs-xen-updates-100321-2' into staging (2021-03-11 16:20:58 +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 9bdb56367679e68e5e71a1c29a1087bda6414b25:
9
for you to fetch changes up to 4b9b70000218640a42c3ea908a12665e5840b6cd:
10
10
11
pvrdma: wean code off pvrdma_ring.h kernel header (2021-03-12 14:08:31 +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
Alexander Bulekov (4):
19
Dr. David Alan Gilbert (9):
17
rtl8139: switch to use qemu_receive_packet() for loopback
20
net: Introduce announce timer
18
pcnet: switch to use qemu_receive_packet() for loopback
21
migration: Add announce parameters
19
cadence_gem: switch to use qemu_receive_packet() for loopback
22
virtio-net: Switch to using announce timer
20
lan9118: switch to use qemu_receive_packet() for loopback
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
21
29
22
Bin Meng (1):
30
Vincenzo Maffione (3):
23
net: Fix build error when DEBUG_NET is on
31
net: netmap: small improvements netmap_send()
32
net: netmap: simplify netmap_receive()
33
net: netmap: improve netmap_receive_iov()
24
34
25
Cornelia Huck (1):
35
Zhang Chen (1):
26
pvrdma: wean code off pvrdma_ring.h kernel header
36
net/colo-compare.c: Remove duplicated code
27
37
28
Jason Wang (9):
38
hmp-commands.hx | 16 +++++
29
virtio-net: calculating proper msix vectors on init
39
hmp.c | 33 ++++++++++
30
net: unbreak well-form id check for "-nic"
40
hmp.h | 1 +
31
e1000: fail early for evil descriptor
41
hw/net/trace-events | 6 ++
32
net: introduce qemu_receive_packet()
42
hw/net/virtio-net.c | 69 +++++++++++++++-----
33
e1000: switch to use qemu_receive_packet() for loopback
43
include/hw/virtio/virtio-net.h | 4 +-
34
dp8393x: switch to use qemu_receive_packet() for loopback packet
44
include/migration/misc.h | 12 +---
35
msf2-mac: switch to use qemu_receive_packet() for loopback
45
include/net/announce.h | 41 ++++++++++++
36
sungem: switch to use qemu_receive_packet() for loopback
46
include/net/net.h | 2 +
37
tx_pkt: switch to use qemu_receive_packet_iov() for loopback
47
include/qemu/typedefs.h | 1 +
38
48
include/sysemu/sysemu.h | 2 -
39
Paolo Bonzini (1):
49
migration/migration.c | 103 +++++++++++++++++++++++++++++-
40
net: validate that ids are well formed
50
migration/migration.h | 4 ++
41
51
migration/savevm.c | 72 +--------------------
42
hw/core/machine.c | 1 +
52
migration/trace-events | 1 -
43
hw/net/cadence_gem.c | 4 +-
53
net/Makefile.objs | 1 +
44
hw/net/dp8393x.c | 2 +-
54
net/announce.c | 140 +++++++++++++++++++++++++++++++++++++++++
45
hw/net/e1000.c | 6 +-
55
net/colo-compare.c | 8 ---
46
hw/net/lan9118.c | 2 +-
56
net/netmap.c | 110 ++++++++++++++------------------
47
hw/net/msf2-emac.c | 2 +-
57
net/trace-events | 3 +
48
hw/net/net_tx_pkt.c | 2 +-
58
qapi/migration.json | 53 +++++++++++++++-
49
hw/net/pcnet.c | 2 +-
59
qapi/net.json | 43 +++++++++++++
50
hw/net/rtl8139.c | 2 +-
60
tests/Makefile.include | 3 +
51
hw/net/sungem.c | 2 +-
61
tests/test-announce-self.c | 82 ++++++++++++++++++++++++
52
hw/rdma/vmw/pvrdma.h | 5 +-
62
tests/test-hmp.c | 1 +
53
hw/rdma/vmw/pvrdma_cmd.c | 6 +-
63
25 files changed, 637 insertions(+), 174 deletions(-)
54
hw/rdma/vmw/pvrdma_dev_ring.c | 41 ++++----
64
create mode 100644 include/net/announce.h
55
hw/rdma/vmw/pvrdma_dev_ring.h | 9 +-
65
create mode 100644 net/announce.c
56
hw/rdma/vmw/pvrdma_main.c | 4 +-
66
create mode 100644 tests/test-announce-self.c
57
hw/virtio/virtio-net-pci.c | 10 +-
58
include/net/net.h | 5 +
59
include/net/queue.h | 8 ++
60
.../drivers/infiniband/hw/vmw_pvrdma/pvrdma_ring.h | 114 ---------------------
61
net/net.c | 53 ++++++++--
62
net/queue.c | 22 ++++
63
scripts/update-linux-headers.sh | 3 +-
64
22 files changed, 142 insertions(+), 163 deletions(-)
65
delete mode 100644 include/standard-headers/drivers/infiniband/hw/vmw_pvrdma/pvrdma_ring.h
66
67
67
68
69
diff view generated by jsdifflib
Deleted patch
1
Currently, the default msix vectors for virtio-net-pci is 3 which is
2
obvious not suitable for multiqueue guest, so we depends on the user
3
or management tools to pass a correct vectors parameter. In fact, we
4
can simplifying this by calculating the number of vectors on realize.
5
1
6
Consider we have N queues, the number of vectors needed is 2*N + 2
7
(#queue pairs + plus one config interrupt and control vq). We didn't
8
check whether or not host support control vq because it was added
9
unconditionally by qemu to avoid breaking legacy guests such as Minix.
10
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com
12
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
13
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Signed-off-by: Jason Wang <jasowang@redhat.com>
15
---
16
hw/core/machine.c | 1 +
17
hw/virtio/virtio-net-pci.c | 10 +++++++++-
18
2 files changed, 10 insertions(+), 1 deletion(-)
19
20
diff --git a/hw/core/machine.c b/hw/core/machine.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/core/machine.c
23
+++ b/hw/core/machine.c
24
@@ -XXX,XX +XXX,XX @@
25
GlobalProperty hw_compat_5_2[] = {
26
{ "ICH9-LPC", "smm-compat", "on"},
27
{ "PIIX4_PM", "smm-compat", "on"},
28
+ { "virtio-net-pci", "vectors", "3"},
29
};
30
const size_t hw_compat_5_2_len = G_N_ELEMENTS(hw_compat_5_2);
31
32
diff --git a/hw/virtio/virtio-net-pci.c b/hw/virtio/virtio-net-pci.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/virtio/virtio-net-pci.c
35
+++ b/hw/virtio/virtio-net-pci.c
36
@@ -XXX,XX +XXX,XX @@ struct VirtIONetPCI {
37
static Property virtio_net_properties[] = {
38
DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
39
VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
40
- DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
41
+ DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
42
+ DEV_NVECTORS_UNSPECIFIED),
43
DEFINE_PROP_END_OF_LIST(),
44
};
45
46
@@ -XXX,XX +XXX,XX @@ static void virtio_net_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
47
DeviceState *qdev = DEVICE(vpci_dev);
48
VirtIONetPCI *dev = VIRTIO_NET_PCI(vpci_dev);
49
DeviceState *vdev = DEVICE(&dev->vdev);
50
+ VirtIONet *net = VIRTIO_NET(vdev);
51
+
52
+ if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) {
53
+ vpci_dev->nvectors = 2 * MAX(net->nic_conf.peers.queues, 1)
54
+ + 1 /* Config interrupt */
55
+ + 1 /* Control vq */;
56
+ }
57
58
virtio_net_set_netclient_name(&dev->vdev, qdev->id,
59
object_get_typename(OBJECT(qdev)));
60
--
61
2.7.4
62
63
diff view generated by jsdifflib
1
From: Alexander Bulekov <alxndr@bu.edu>
1
From: Zhang Chen <chen.zhang@intel.com>
2
2
3
This patch switches to use qemu_receive_packet() which can detect
3
Fix duplicated code:
4
reentrancy and return early.
4
https://bugs.launchpad.net/qemu/+bug/1811499
5
5
6
This is intended to address CVE-2021-3416.
6
Reviewed-by: Thomas Huth <thuth@redhat.com>
7
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Cc: Prasad J Pandit <ppandit@redhat.com>
8
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
9
Cc: qemu-stable@nongnu.org
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com
11
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
---
10
---
14
hw/net/lan9118.c | 2 +-
11
net/colo-compare.c | 8 --------
15
1 file changed, 1 insertion(+), 1 deletion(-)
12
1 file changed, 8 deletions(-)
16
13
17
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
14
diff --git a/net/colo-compare.c b/net/colo-compare.c
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/net/lan9118.c
16
--- a/net/colo-compare.c
20
+++ b/hw/net/lan9118.c
17
+++ b/net/colo-compare.c
21
@@ -XXX,XX +XXX,XX @@ static void do_tx_packet(lan9118_state *s)
18
@@ -XXX,XX +XXX,XX @@ static bool colo_mark_tcp_pkt(Packet *ppkt, Packet *spkt,
22
/* FIXME: Honor TX disable, and allow queueing of packets. */
19
return true;
23
if (s->phy_control & 0x4000) {
20
}
24
/* This assumes the receive routine doesn't touch the VLANClient. */
25
- lan9118_receive(qemu_get_queue(s->nic), s->txp->data, s->txp->len);
26
+ qemu_receive_packet(qemu_get_queue(s->nic), s->txp->data, s->txp->len);
27
} else {
28
qemu_send_packet(qemu_get_queue(s->nic), s->txp->data, s->txp->len);
29
}
21
}
22
- if (ppkt->tcp_seq == spkt->tcp_seq && ppkt->seq_end == spkt->seq_end) {
23
- if (colo_compare_packet_payload(ppkt, spkt,
24
- ppkt->header_size, spkt->header_size,
25
- ppkt->payload_size)) {
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)) {
30
--
33
--
31
2.7.4
34
2.5.0
32
35
33
36
diff view generated by jsdifflib
1
From: Alexander Bulekov <alxndr@bu.edu>
1
From: Vincenzo Maffione <v.maffione@gmail.com>
2
2
3
This patch switches to use qemu_receive_packet() which can detect
3
This change improves the handling of incomplete multi-slot packets
4
reentrancy and return early.
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.
5
9
6
This is intended to address CVE-2021-3416.
10
Signed-off-by: Vincenzo Maffione <v.maffione@gmail.com>
7
8
Cc: Prasad J Pandit <ppandit@redhat.com>
9
Cc: qemu-stable@nongnu.org
10
Buglink: https://bugs.launchpad.net/qemu/+bug/1910826
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com
12
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
13
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
14
---
12
---
15
hw/net/rtl8139.c | 2 +-
13
net/netmap.c | 31 +++++++++++++++++++------------
16
1 file changed, 1 insertion(+), 1 deletion(-)
14
1 file changed, 19 insertions(+), 12 deletions(-)
17
15
18
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
16
diff --git a/net/netmap.c b/net/netmap.c
19
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/net/rtl8139.c
18
--- a/net/netmap.c
21
+++ b/hw/net/rtl8139.c
19
+++ b/net/netmap.c
22
@@ -XXX,XX +XXX,XX @@ static void rtl8139_transfer_frame(RTL8139State *s, uint8_t *buf, int size,
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;
23
}
63
}
24
64
25
DPRINTF("+++ transmit loopback mode\n");
65
iovsize = qemu_sendv_packet_async(&s->nc, s->iov, iovcnt,
26
- rtl8139_do_receive(qemu_get_queue(s->nic), buf, size, do_interrupt);
66
netmap_send_completed);
27
+ qemu_receive_packet(qemu_get_queue(s->nic), buf, size);
67
28
68
+ /* Release the slots to the kernel. */
29
if (iov) {
69
+ ring->head = i;
30
g_free(buf2);
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
}
31
--
79
--
32
2.7.4
80
2.5.0
33
81
34
82
diff view generated by jsdifflib
1
From: Cornelia Huck <cohuck@redhat.com>
1
From: Vincenzo Maffione <v.maffione@gmail.com>
2
2
3
The pvrdma code relies on the pvrdma_ring.h kernel header for some
3
Improve code reuse by implementing netmap_receive() with a call
4
basic ring buffer handling. The content of that header isn't very
4
to netmap_receive_iov().
5
exciting, but contains some (q)atomic_*() invocations that (a)
6
cause manual massaging when doing a headers update, and (b) are
7
an indication that we probably should not be importing that header
8
at all.
9
5
10
Let's reimplement the ring buffer handling directly in the pvrdma
6
Signed-off-by: Vincenzo Maffione <v.maffione@gmail.com>
11
code instead. This arguably also improves readability of the code.
12
13
Importing the header can now be dropped.
14
15
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
16
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
17
Reviewed-by: Yuval Shaia <yuval.shaia.ml@gmail.com>
18
Tested-by: Yuval Shaia <yuval.shaia.ml@gmail.com>
19
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
20
---
8
---
21
hw/rdma/vmw/pvrdma.h | 5 +-
9
net/netmap.c | 50 +++++++++++---------------------------------------
22
hw/rdma/vmw/pvrdma_cmd.c | 6 +-
10
1 file changed, 11 insertions(+), 39 deletions(-)
23
hw/rdma/vmw/pvrdma_dev_ring.c | 41 ++++----
24
hw/rdma/vmw/pvrdma_dev_ring.h | 9 +-
25
hw/rdma/vmw/pvrdma_main.c | 4 +-
26
.../drivers/infiniband/hw/vmw_pvrdma/pvrdma_ring.h | 114 ---------------------
27
scripts/update-linux-headers.sh | 3 +-
28
7 files changed, 38 insertions(+), 144 deletions(-)
29
delete mode 100644 include/standard-headers/drivers/infiniband/hw/vmw_pvrdma/pvrdma_ring.h
30
11
31
diff --git a/hw/rdma/vmw/pvrdma.h b/hw/rdma/vmw/pvrdma.h
12
diff --git a/net/netmap.c b/net/netmap.c
32
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
33
--- a/hw/rdma/vmw/pvrdma.h
14
--- a/net/netmap.c
34
+++ b/hw/rdma/vmw/pvrdma.h
15
+++ b/net/netmap.c
35
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ static void netmap_writable(void *opaque)
36
#include "../rdma_backend_defs.h"
17
qemu_flush_queued_packets(&s->nc);
37
#include "../rdma_rm_defs.h"
38
39
-#include "standard-headers/drivers/infiniband/hw/vmw_pvrdma/pvrdma_ring.h"
40
#include "standard-headers/drivers/infiniband/hw/vmw_pvrdma/pvrdma_dev_api.h"
41
#include "pvrdma_dev_ring.h"
42
#include "qom/object.h"
43
@@ -XXX,XX +XXX,XX @@ typedef struct DSRInfo {
44
union pvrdma_cmd_req *req;
45
union pvrdma_cmd_resp *rsp;
46
47
- struct pvrdma_ring *async_ring_state;
48
+ PvrdmaRingState *async_ring_state;
49
PvrdmaRing async;
50
51
- struct pvrdma_ring *cq_ring_state;
52
+ PvrdmaRingState *cq_ring_state;
53
PvrdmaRing cq;
54
} DSRInfo;
55
56
diff --git a/hw/rdma/vmw/pvrdma_cmd.c b/hw/rdma/vmw/pvrdma_cmd.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/hw/rdma/vmw/pvrdma_cmd.c
59
+++ b/hw/rdma/vmw/pvrdma_cmd.c
60
@@ -XXX,XX +XXX,XX @@ static int create_cq_ring(PCIDevice *pci_dev , PvrdmaRing **ring,
61
r = g_malloc(sizeof(*r));
62
*ring = r;
63
64
- r->ring_state = (struct pvrdma_ring *)
65
+ r->ring_state = (PvrdmaRingState *)
66
rdma_pci_dma_map(pci_dev, tbl[0], TARGET_PAGE_SIZE);
67
68
if (!r->ring_state) {
69
@@ -XXX,XX +XXX,XX @@ static int create_qp_rings(PCIDevice *pci_dev, uint64_t pdir_dma,
70
*rings = sr;
71
72
/* Create send ring */
73
- sr->ring_state = (struct pvrdma_ring *)
74
+ sr->ring_state = (PvrdmaRingState *)
75
rdma_pci_dma_map(pci_dev, tbl[0], TARGET_PAGE_SIZE);
76
if (!sr->ring_state) {
77
rdma_error_report("Failed to map to QP ring state");
78
@@ -XXX,XX +XXX,XX @@ static int create_srq_ring(PCIDevice *pci_dev, PvrdmaRing **ring,
79
r = g_malloc(sizeof(*r));
80
*ring = r;
81
82
- r->ring_state = (struct pvrdma_ring *)
83
+ r->ring_state = (PvrdmaRingState *)
84
rdma_pci_dma_map(pci_dev, tbl[0], TARGET_PAGE_SIZE);
85
if (!r->ring_state) {
86
rdma_error_report("Failed to map tp SRQ ring state");
87
diff --git a/hw/rdma/vmw/pvrdma_dev_ring.c b/hw/rdma/vmw/pvrdma_dev_ring.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/hw/rdma/vmw/pvrdma_dev_ring.c
90
+++ b/hw/rdma/vmw/pvrdma_dev_ring.c
91
@@ -XXX,XX +XXX,XX @@
92
#include "trace.h"
93
94
#include "../rdma_utils.h"
95
-#include "standard-headers/drivers/infiniband/hw/vmw_pvrdma/pvrdma_ring.h"
96
#include "pvrdma_dev_ring.h"
97
98
int pvrdma_ring_init(PvrdmaRing *ring, const char *name, PCIDevice *dev,
99
- struct pvrdma_ring *ring_state, uint32_t max_elems,
100
+ PvrdmaRingState *ring_state, uint32_t max_elems,
101
size_t elem_sz, dma_addr_t *tbl, uint32_t npages)
102
{
103
int i;
104
@@ -XXX,XX +XXX,XX @@ out:
105
106
void *pvrdma_ring_next_elem_read(PvrdmaRing *ring)
107
{
108
- int e;
109
- unsigned int idx = 0, offset;
110
+ unsigned int idx, offset;
111
+ const uint32_t tail = qatomic_read(&ring->ring_state->prod_tail);
112
+ const uint32_t head = qatomic_read(&ring->ring_state->cons_head);
113
114
- e = pvrdma_idx_ring_has_data(ring->ring_state, ring->max_elems, &idx);
115
- if (e <= 0) {
116
+ if (tail & ~((ring->max_elems << 1) - 1) ||
117
+ head & ~((ring->max_elems << 1) - 1) ||
118
+ tail == head) {
119
trace_pvrdma_ring_next_elem_read_no_data(ring->name);
120
return NULL;
121
}
122
123
+ idx = head & (ring->max_elems - 1);
124
offset = idx * ring->elem_sz;
125
return ring->pages[offset / TARGET_PAGE_SIZE] + (offset % TARGET_PAGE_SIZE);
126
}
18
}
127
19
128
void pvrdma_ring_read_inc(PvrdmaRing *ring)
20
-static ssize_t netmap_receive(NetClientState *nc,
129
{
21
- const uint8_t *buf, size_t size)
130
- pvrdma_idx_ring_inc(&ring->ring_state->cons_head, ring->max_elems);
22
-{
131
+ uint32_t idx = qatomic_read(&ring->ring_state->cons_head);
23
- NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
132
+
24
- struct netmap_ring *ring = s->tx;
133
+ idx = (idx + 1) & ((ring->max_elems << 1) - 1);
25
- uint32_t i;
134
+ qatomic_set(&ring->ring_state->cons_head, idx);
26
- uint32_t idx;
135
}
27
- uint8_t *dst;
136
28
-
137
void *pvrdma_ring_next_elem_write(PvrdmaRing *ring)
29
- if (unlikely(!ring)) {
138
{
30
- /* Drop. */
139
- int idx;
31
- return size;
140
- unsigned int offset, tail;
141
+ unsigned int idx, offset;
142
+ const uint32_t tail = qatomic_read(&ring->ring_state->prod_tail);
143
+ const uint32_t head = qatomic_read(&ring->ring_state->cons_head);
144
145
- idx = pvrdma_idx_ring_has_space(ring->ring_state, ring->max_elems, &tail);
146
- if (idx <= 0) {
147
+ if (tail & ~((ring->max_elems << 1) - 1) ||
148
+ head & ~((ring->max_elems << 1) - 1) ||
149
+ tail == (head ^ ring->max_elems)) {
150
rdma_error_report("CQ is full");
151
return NULL;
152
}
153
154
- idx = pvrdma_idx(&ring->ring_state->prod_tail, ring->max_elems);
155
- if (idx < 0 || tail != idx) {
156
- rdma_error_report("Invalid idx %d", idx);
157
- return NULL;
158
- }
32
- }
159
-
33
-
160
+ idx = tail & (ring->max_elems - 1);
34
- if (unlikely(size > ring->nr_buf_size)) {
161
offset = idx * ring->elem_sz;
35
- RD(5, "[netmap_receive] drop packet of size %d > %d\n",
162
return ring->pages[offset / TARGET_PAGE_SIZE] + (offset % TARGET_PAGE_SIZE);
36
- (int)size, ring->nr_buf_size);
163
}
37
- return size;
164
38
- }
165
void pvrdma_ring_write_inc(PvrdmaRing *ring)
166
{
167
- pvrdma_idx_ring_inc(&ring->ring_state->prod_tail, ring->max_elems);
168
+ uint32_t idx = qatomic_read(&ring->ring_state->prod_tail);
169
+
170
+ idx = (idx + 1) & ((ring->max_elems << 1) - 1);
171
+ qatomic_set(&ring->ring_state->prod_tail, idx);
172
}
173
174
void pvrdma_ring_free(PvrdmaRing *ring)
175
diff --git a/hw/rdma/vmw/pvrdma_dev_ring.h b/hw/rdma/vmw/pvrdma_dev_ring.h
176
index XXXXXXX..XXXXXXX 100644
177
--- a/hw/rdma/vmw/pvrdma_dev_ring.h
178
+++ b/hw/rdma/vmw/pvrdma_dev_ring.h
179
@@ -XXX,XX +XXX,XX @@
180
181
#define MAX_RING_NAME_SZ 32
182
183
+typedef struct PvrdmaRingState {
184
+ int prod_tail; /* producer tail */
185
+ int cons_head; /* consumer head */
186
+} PvrdmaRingState;
187
+
188
typedef struct PvrdmaRing {
189
char name[MAX_RING_NAME_SZ];
190
PCIDevice *dev;
191
uint32_t max_elems;
192
size_t elem_sz;
193
- struct pvrdma_ring *ring_state; /* used only for unmap */
194
+ PvrdmaRingState *ring_state; /* used only for unmap */
195
int npages;
196
void **pages;
197
} PvrdmaRing;
198
199
int pvrdma_ring_init(PvrdmaRing *ring, const char *name, PCIDevice *dev,
200
- struct pvrdma_ring *ring_state, uint32_t max_elems,
201
+ PvrdmaRingState *ring_state, uint32_t max_elems,
202
size_t elem_sz, dma_addr_t *tbl, uint32_t npages);
203
void *pvrdma_ring_next_elem_read(PvrdmaRing *ring);
204
void pvrdma_ring_read_inc(PvrdmaRing *ring);
205
diff --git a/hw/rdma/vmw/pvrdma_main.c b/hw/rdma/vmw/pvrdma_main.c
206
index XXXXXXX..XXXXXXX 100644
207
--- a/hw/rdma/vmw/pvrdma_main.c
208
+++ b/hw/rdma/vmw/pvrdma_main.c
209
@@ -XXX,XX +XXX,XX @@ static void free_dev_ring(PCIDevice *pci_dev, PvrdmaRing *ring,
210
rdma_pci_dma_unmap(pci_dev, ring_state, TARGET_PAGE_SIZE);
211
}
212
213
-static int init_dev_ring(PvrdmaRing *ring, struct pvrdma_ring **ring_state,
214
+static int init_dev_ring(PvrdmaRing *ring, PvrdmaRingState **ring_state,
215
const char *name, PCIDevice *pci_dev,
216
dma_addr_t dir_addr, uint32_t num_pages)
217
{
218
@@ -XXX,XX +XXX,XX @@ static int init_dev_ring(PvrdmaRing *ring, struct pvrdma_ring **ring_state,
219
/* RX ring is the second */
220
(*ring_state)++;
221
rc = pvrdma_ring_init(ring, name, pci_dev,
222
- (struct pvrdma_ring *)*ring_state,
223
+ (PvrdmaRingState *)*ring_state,
224
(num_pages - 1) * TARGET_PAGE_SIZE /
225
sizeof(struct pvrdma_cqne),
226
sizeof(struct pvrdma_cqne),
227
diff --git a/include/standard-headers/drivers/infiniband/hw/vmw_pvrdma/pvrdma_ring.h b/include/standard-headers/drivers/infiniband/hw/vmw_pvrdma/pvrdma_ring.h
228
deleted file mode 100644
229
index XXXXXXX..XXXXXXX
230
--- a/include/standard-headers/drivers/infiniband/hw/vmw_pvrdma/pvrdma_ring.h
231
+++ /dev/null
232
@@ -XXX,XX +XXX,XX @@
233
-/*
234
- * Copyright (c) 2012-2016 VMware, Inc. All rights reserved.
235
- *
236
- * This program is free software; you can redistribute it and/or
237
- * modify it under the terms of EITHER the GNU General Public License
238
- * version 2 as published by the Free Software Foundation or the BSD
239
- * 2-Clause License. This program is distributed in the hope that it
240
- * will be useful, but WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED
241
- * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
242
- * See the GNU General Public License version 2 for more details at
243
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html.
244
- *
245
- * You should have received a copy of the GNU General Public License
246
- * along with this program available in the file COPYING in the main
247
- * directory of this source tree.
248
- *
249
- * The BSD 2-Clause License
250
- *
251
- * Redistribution and use in source and binary forms, with or
252
- * without modification, are permitted provided that the following
253
- * conditions are met:
254
- *
255
- * - Redistributions of source code must retain the above
256
- * copyright notice, this list of conditions and the following
257
- * disclaimer.
258
- *
259
- * - Redistributions in binary form must reproduce the above
260
- * copyright notice, this list of conditions and the following
261
- * disclaimer in the documentation and/or other materials
262
- * provided with the distribution.
263
- *
264
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
265
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
266
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
267
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
268
- * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
269
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
270
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
271
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
272
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
273
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
274
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
275
- * OF THE POSSIBILITY OF SUCH DAMAGE.
276
- */
277
-
39
-
278
-#ifndef __PVRDMA_RING_H__
40
- if (nm_ring_empty(ring)) {
279
-#define __PVRDMA_RING_H__
41
- /* No available slots in the netmap TX ring. */
42
- netmap_write_poll(s, true);
43
- return 0;
44
- }
280
-
45
-
281
-#include "standard-headers/linux/types.h"
46
- i = ring->cur;
47
- idx = ring->slot[i].buf_idx;
48
- dst = (uint8_t *)NETMAP_BUF(ring, idx);
282
-
49
-
283
-#define PVRDMA_INVALID_IDX    -1    /* Invalid index. */
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);
284
-
55
-
285
-struct pvrdma_ring {
56
- return size;
286
-    int prod_tail;    /* Producer tail. */
287
-    int cons_head;    /* Consumer head. */
288
-};
289
-
290
-struct pvrdma_ring_state {
291
-    struct pvrdma_ring tx;    /* Tx ring. */
292
-    struct pvrdma_ring rx;    /* Rx ring. */
293
-};
294
-
295
-static inline int pvrdma_idx_valid(uint32_t idx, uint32_t max_elems)
296
-{
297
-    /* Generates fewer instructions than a less-than. */
298
-    return (idx & ~((max_elems << 1) - 1)) == 0;
299
-}
57
-}
300
-
58
-
301
-static inline int32_t pvrdma_idx(int *var, uint32_t max_elems)
59
static ssize_t netmap_receive_iov(NetClientState *nc,
302
-{
60
const struct iovec *iov, int iovcnt)
303
-    const unsigned int idx = qatomic_read(var);
61
{
304
-
62
@@ -XXX,XX +XXX,XX @@ static ssize_t netmap_receive_iov(NetClientState *nc,
305
-    if (pvrdma_idx_valid(idx, max_elems))
63
return iov_size(iov, iovcnt);
306
-        return idx & (max_elems - 1);
64
}
307
-    return PVRDMA_INVALID_IDX;
65
308
-}
66
+static ssize_t netmap_receive(NetClientState *nc,
309
-
67
+ const uint8_t *buf, size_t size)
310
-static inline void pvrdma_idx_ring_inc(int *var, uint32_t max_elems)
68
+{
311
-{
69
+ struct iovec iov;
312
-    uint32_t idx = qatomic_read(var) + 1;    /* Increment. */
70
+
313
-
71
+ iov.iov_base = (void *)buf;
314
-    idx &= (max_elems << 1) - 1;        /* Modulo size, flip gen. */
72
+ iov.iov_len = size;
315
-    qatomic_set(var, idx);
73
+
316
-}
74
+ return netmap_receive_iov(nc, &iov, 1);
317
-
75
+}
318
-static inline int32_t pvrdma_idx_ring_has_space(const struct pvrdma_ring *r,
76
+
319
-                     uint32_t max_elems, uint32_t *out_tail)
77
/* Complete a previous send (backend --> guest) and enable the
320
-{
78
fd_read callback. */
321
-    const uint32_t tail = qatomic_read(&r->prod_tail);
79
static void netmap_send_completed(NetClientState *nc, ssize_t len)
322
-    const uint32_t head = qatomic_read(&r->cons_head);
323
-
324
-    if (pvrdma_idx_valid(tail, max_elems) &&
325
-     pvrdma_idx_valid(head, max_elems)) {
326
-        *out_tail = tail & (max_elems - 1);
327
-        return tail != (head ^ max_elems);
328
-    }
329
-    return PVRDMA_INVALID_IDX;
330
-}
331
-
332
-static inline int32_t pvrdma_idx_ring_has_data(const struct pvrdma_ring *r,
333
-                     uint32_t max_elems, uint32_t *out_head)
334
-{
335
-    const uint32_t tail = qatomic_read(&r->prod_tail);
336
-    const uint32_t head = qatomic_read(&r->cons_head);
337
-
338
-    if (pvrdma_idx_valid(tail, max_elems) &&
339
-     pvrdma_idx_valid(head, max_elems)) {
340
-        *out_head = head & (max_elems - 1);
341
-        return tail != head;
342
-    }
343
-    return PVRDMA_INVALID_IDX;
344
-}
345
-
346
-#endif /* __PVRDMA_RING_H__ */
347
diff --git a/scripts/update-linux-headers.sh b/scripts/update-linux-headers.sh
348
index XXXXXXX..XXXXXXX 100755
349
--- a/scripts/update-linux-headers.sh
350
+++ b/scripts/update-linux-headers.sh
351
@@ -XXX,XX +XXX,XX @@ sed -e '1h;2,$H;$!d;g' -e 's/[^};]*pvrdma[^(| ]*([^)]*);//g' \
352
"$linux/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h" > \
353
"$tmp_pvrdma_verbs";
354
355
-for i in "$linux/drivers/infiniband/hw/vmw_pvrdma/pvrdma_ring.h" \
356
- "$linux/drivers/infiniband/hw/vmw_pvrdma/pvrdma_dev_api.h" \
357
+for i in "$linux/drivers/infiniband/hw/vmw_pvrdma/pvrdma_dev_api.h" \
358
"$tmp_pvrdma_verbs"; do \
359
cp_portable "$i" \
360
"$output/include/standard-headers/drivers/infiniband/hw/vmw_pvrdma/"
361
--
80
--
362
2.7.4
81
2.5.0
363
82
364
83
diff view generated by jsdifflib
1
From: Alexander Bulekov <alxndr@bu.edu>
1
From: Vincenzo Maffione <v.maffione@gmail.com>
2
2
3
This patch switches to use qemu_receive_packet() which can detect
3
Changes:
4
reentrancy and return early.
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).
5
13
6
This is intended to address CVE-2021-3416.
14
Signed-off-by: Vincenzo Maffione <v.maffione@gmail.com>
7
8
Cc: Prasad J Pandit <ppandit@redhat.com>
9
Cc: qemu-stable@nongnu.org
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
15
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
---
16
---
14
hw/net/cadence_gem.c | 4 ++--
17
net/netmap.c | 29 +++++++++++++++++------------
15
1 file changed, 2 insertions(+), 2 deletions(-)
18
1 file changed, 17 insertions(+), 12 deletions(-)
16
19
17
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
20
diff --git a/net/netmap.c b/net/netmap.c
18
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/net/cadence_gem.c
22
--- a/net/netmap.c
20
+++ b/hw/net/cadence_gem.c
23
+++ b/net/netmap.c
21
@@ -XXX,XX +XXX,XX @@ static void gem_transmit(CadenceGEMState *s)
24
@@ -XXX,XX +XXX,XX @@ static ssize_t netmap_receive_iov(NetClientState *nc,
22
/* Send the packet somewhere */
25
{
23
if (s->phy_loop || (s->regs[GEM_NWCTRL] &
26
NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
24
GEM_NWCTRL_LOCALLOOP)) {
27
struct netmap_ring *ring = s->tx;
25
- gem_receive(qemu_get_queue(s->nic), s->tx_packet,
28
+ unsigned int tail = ring->tail;
26
- total_bytes);
29
+ ssize_t totlen = 0;
27
+ qemu_receive_packet(qemu_get_queue(s->nic), s->tx_packet,
30
uint32_t last;
28
+ total_bytes);
31
uint32_t idx;
29
} else {
32
uint8_t *dst;
30
qemu_send_packet(qemu_get_queue(s->nic), s->tx_packet,
33
int j;
31
total_bytes);
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,
32
--
91
--
33
2.7.4
92
2.5.0
34
93
35
94
diff view generated by jsdifflib
1
From: Alexander Bulekov <alxndr@bu.edu>
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
2
2
3
This patch switches to use qemu_receive_packet() which can detect
3
The 'announce timer' will be used by migration, and explicit
4
reentrancy and return early.
4
requests for qemu to perform network announces.
5
5
6
This is intended to address CVE-2021-3416.
6
Based on the work by Germano Veit Michel <germano@redhat.com>
7
7
and Vlad Yasevich <vyasevic@redhat.com>
8
Cc: Prasad J Pandit <ppandit@redhat.com>
8
9
Cc: qemu-stable@nongnu.org
9
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
10
Buglink: https://bugs.launchpad.net/qemu/+bug/1917085
10
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com
12
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
13
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
14
---
12
---
15
hw/net/pcnet.c | 2 +-
13
include/net/announce.h | 39 ++++++++++++++++++++++++++++++++
16
1 file changed, 1 insertion(+), 1 deletion(-)
14
include/qemu/typedefs.h | 1 +
17
15
migration/migration.c | 1 +
18
diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c
16
net/Makefile.objs | 1 +
19
index XXXXXXX..XXXXXXX 100644
17
net/announce.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++
20
--- a/hw/net/pcnet.c
18
qapi/net.json | 23 +++++++++++++++++++
21
+++ b/hw/net/pcnet.c
19
6 files changed, 125 insertions(+)
22
@@ -XXX,XX +XXX,XX @@ txagain:
20
create mode 100644 include/net/announce.h
23
if (BCR_SWSTYLE(s) == 1)
21
create mode 100644 net/announce.c
24
add_crc = !GET_FIELD(tmd.status, TMDS, NOFCS);
22
25
s->looptest = add_crc ? PCNET_LOOPTEST_CRC : PCNET_LOOPTEST_NOCRC;
23
diff --git a/include/net/announce.h b/include/net/announce.h
26
- pcnet_receive(qemu_get_queue(s->nic), s->buffer, s->xmit_pos);
24
new file mode 100644
27
+ qemu_receive_packet(qemu_get_queue(s->nic), s->buffer, s->xmit_pos);
25
index XXXXXXX..XXXXXXX
28
s->looptest = 0;
26
--- /dev/null
29
} else {
27
+++ b/include/net/announce.h
30
if (s->nic) {
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' } }
31
--
201
--
32
2.7.4
202
2.5.0
33
203
34
204
diff view generated by jsdifflib
1
From: Bin Meng <bin.meng@windriver.com>
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
2
2
3
"qemu-common.h" should be included to provide the forward declaration
3
Add migration parameters that control RARP/GARP announcement timeouts.
4
of qemu_hexdump() when DEBUG_NET is on.
4
5
5
Based on earlier patches by myself and
6
Signed-off-by: Bin Meng <bin.meng@windriver.com>
6
Vladislav Yasevich <vyasevic@redhat.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@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>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
12
---
10
net/net.c | 1 +
13
hmp.c | 28 +++++++++++++
11
1 file changed, 1 insertion(+)
14
include/migration/misc.h | 2 +
12
15
migration/migration.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++
13
diff --git a/net/net.c b/net/net.c
16
qapi/migration.json | 53 +++++++++++++++++++++++--
17
4 files changed, 180 insertions(+), 3 deletions(-)
18
19
diff --git a/hmp.c b/hmp.c
14
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
15
--- a/net/net.c
21
--- a/hmp.c
16
+++ b/net/net.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
17
@@ -XXX,XX +XXX,XX @@
89
@@ -XXX,XX +XXX,XX @@
18
*/
90
*/
19
91
#define DEFAULT_MIGRATE_MAX_POSTCOPY_BANDWIDTH 0
20
#include "qemu/osdep.h"
92
21
+#include "qemu-common.h"
93
+/*
22
94
+ * Parameters for self_announce_delay giving a stream of RARP/ARP
23
#include "net/net.h"
95
+ * packets after migration.
24
#include "clients.h"
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',
25
--
344
--
26
2.7.4
345
2.5.0
27
346
28
347
diff view generated by jsdifflib
1
During procss_tx_desc(), driver can try to chain data descriptor with
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
2
legacy descriptor, when will lead underflow for the following
3
calculation in process_tx_desc() for bytes:
4
2
5
if (tp->size + bytes > msh)
3
Switch virtio's self announcement to use the AnnounceTimer.
6
bytes = msh - tp->size;
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.
7
9
8
This will lead a infinite loop. So check and fail early if tp->size if
10
Based on earlier patches by myself and
9
greater or equal to msh.
11
Vladislav Yasevich <vyasevic@redhat.com>
10
12
11
Reported-by: Alexander Bulekov <alxndr@bu.edu>
13
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
12
Reported-by: Cheolwoo Myung <cwmyung@snu.ac.kr>
14
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
13
Reported-by: Ruhr-University Bochum <bugs-syssec@rub.de>
14
Cc: Prasad J Pandit <ppandit@redhat.com>
15
Cc: qemu-stable@nongnu.org
16
Signed-off-by: Jason Wang <jasowang@redhat.com>
15
Signed-off-by: Jason Wang <jasowang@redhat.com>
17
---
16
---
18
hw/net/e1000.c | 4 ++++
17
hw/net/trace-events | 5 +++++
19
1 file changed, 4 insertions(+)
18
hw/net/virtio-net.c | 36 +++++++++++++++++++++++-------------
19
include/hw/virtio/virtio-net.h | 4 ++--
20
3 files changed, 30 insertions(+), 15 deletions(-)
20
21
21
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
22
diff --git a/hw/net/trace-events b/hw/net/trace-events
22
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/net/e1000.c
24
--- a/hw/net/trace-events
24
+++ b/hw/net/e1000.c
25
+++ b/hw/net/trace-events
25
@@ -XXX,XX +XXX,XX @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
26
@@ -XXX,XX +XXX,XX @@ sunhme_rx_filter_reject(void) "rejecting incoming frame"
26
msh = tp->tso_props.hdr_len + tp->tso_props.mss;
27
sunhme_rx_filter_accept(void) "accepting incoming frame"
27
do {
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)"
28
bytes = split_size;
29
sunhme_rx_xsum_calc(uint16_t xsum) "calculated incoming xsum as 0x%x"
29
+ if (tp->size >= msh) {
30
+
30
+ goto eop;
31
+# hw/net/virtio-net.c
31
+ }
32
+virtio_net_announce_timer(int round) "%d"
32
if (tp->size + bytes > msh)
33
+virtio_net_handle_announce(int round) "%d"
33
bytes = msh - tp->size;
34
+virtio_net_post_load_device(void)
34
35
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
35
@@ -XXX,XX +XXX,XX @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
36
index XXXXXXX..XXXXXXX 100644
36
tp->size += split_size;
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
+ }
37
}
116
}
38
117
39
+eop:
118
return 0;
40
if (!(txd_lower & E1000_TXD_CMD_EOP))
119
@@ -XXX,XX +XXX,XX @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
41
return;
120
qemu_macaddr_default_if_unset(&n->nic_conf.macaddr);
42
if (!(tp->cptse && tp->size < tp->tso_props.hdr_len)) {
121
memcpy(&n->mac[0], &n->nic_conf.macaddr, sizeof(n->mac));
122
n->status = VIRTIO_NET_S_LINK_UP;
123
- n->announce_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL,
124
- virtio_net_announce_timer, n);
125
+ qemu_announce_timer_reset(&n->announce_timer, migrate_announce_params(),
126
+ QEMU_CLOCK_VIRTUAL,
127
+ virtio_net_announce_timer, n);
128
129
if (n->netclient_type) {
130
/*
131
@@ -XXX,XX +XXX,XX @@ static void virtio_net_device_unrealize(DeviceState *dev, Error **errp)
132
virtio_net_del_queue(n, i);
133
}
134
135
- timer_del(n->announce_timer);
136
- timer_free(n->announce_timer);
137
+ qemu_announce_timer_del(&n->announce_timer);
138
g_free(n->vqs);
139
qemu_del_nic(n->nic);
140
virtio_net_rsc_cleanup(n);
141
diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
142
index XXXXXXX..XXXXXXX 100644
143
--- a/include/hw/virtio/virtio-net.h
144
+++ b/include/hw/virtio/virtio-net.h
145
@@ -XXX,XX +XXX,XX @@
146
#include "qemu/units.h"
147
#include "standard-headers/linux/virtio_net.h"
148
#include "hw/virtio/virtio.h"
149
+#include "net/announce.h"
150
151
#define TYPE_VIRTIO_NET "virtio-net-device"
152
#define VIRTIO_NET(obj) \
153
@@ -XXX,XX +XXX,XX @@ struct VirtIONet {
154
char *netclient_name;
155
char *netclient_type;
156
uint64_t curr_guest_offloads;
157
- QEMUTimer *announce_timer;
158
- int announce_counter;
159
+ AnnounceTimer announce_timer;
160
bool needs_vnet_hdr_swap;
161
bool mtu_bypass_backend;
162
};
43
--
163
--
44
2.7.4
164
2.5.0
45
165
46
166
diff view generated by jsdifflib
1
The auto genreated id for "-nic" has "_" prefix which can't satisfy
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
2
the well-formed id check that is introduced by
2
3
871579b9834aca517dc2d4941691a1d2082db6f2 ("net: validate that ids are
3
Switch the announcements to using the new announce timer.
4
well formed"). Fix this by simply removing the "__" prefix.
4
Move the code that does it to announce.c rather than savevm
5
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>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
---
14
---
8
net/net.c | 2 +-
15
include/migration/misc.h | 10 -------
9
1 file changed, 1 insertion(+), 1 deletion(-)
16
include/net/announce.h | 2 ++
10
17
include/sysemu/sysemu.h | 2 --
11
diff --git a/net/net.c b/net/net.c
18
migration/migration.c | 2 +-
12
index XXXXXXX..XXXXXXX 100644
19
migration/migration.h | 4 +++
13
--- a/net/net.c
20
migration/savevm.c | 72 ++----------------------------------------------
14
+++ b/net/net.c
21
migration/trace-events | 1 -
15
@@ -XXX,XX +XXX,XX @@ static int net_param_nic(void *dummy, QemuOpts *opts, Error **errp)
22
net/announce.c | 68 +++++++++++++++++++++++++++++++++++++++++++++
16
/* Create an ID if the user did not specify one */
23
net/trace-events | 3 ++
17
nd_id = g_strdup(qemu_opts_id(opts));
24
9 files changed, 81 insertions(+), 83 deletions(-)
18
if (!nd_id) {
25
19
- nd_id = g_strdup_printf("__org.qemu.nic%i", idx);
26
diff --git a/include/migration/misc.h b/include/migration/misc.h
20
+ nd_id = g_strdup_printf("org.qemu.nic%i", idx);
27
index XXXXXXX..XXXXXXX 100644
21
qemu_opts_set_id(opts, nd_id);
28
--- a/include/migration/misc.h
22
}
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"
23
318
24
--
319
--
25
2.7.4
320
2.5.0
26
321
27
322
diff view generated by jsdifflib
1
Some NIC supports loopback mode and this is done by calling
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
2
nc->info->receive() directly which in fact suppresses the effort of
3
reentrancy check that is done in qemu_net_queue_send().
4
2
5
Unfortunately we can't use qemu_net_queue_send() here since for
3
Some network devices have a capability to do self announcements
6
loopback there's no sender as peer, so this patch introduce a
4
(ex: virtio-net). Add infrastructure that would allow devices
7
qemu_receive_packet() which is used for implementing loopback mode
5
to expose this ability.
8
for a NIC with this check.
9
6
10
NIC that supports loopback mode will be converted to this helper.
7
Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
11
8
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
12
This is intended to address CVE-2021-3416.
9
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
13
14
Cc: Prasad J Pandit <ppandit@redhat.com>
15
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
16
Cc: qemu-stable@nongnu.org
17
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
18
---
11
---
19
include/net/net.h | 5 +++++
12
include/net/net.h | 2 ++
20
include/net/queue.h | 8 ++++++++
13
net/announce.c | 5 +++++
21
net/net.c | 38 +++++++++++++++++++++++++++++++-------
14
2 files changed, 7 insertions(+)
22
net/queue.c | 22 ++++++++++++++++++++++
23
4 files changed, 66 insertions(+), 7 deletions(-)
24
15
25
diff --git a/include/net/net.h b/include/net/net.h
16
diff --git a/include/net/net.h b/include/net/net.h
26
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
27
--- a/include/net/net.h
18
--- a/include/net/net.h
28
+++ b/include/net/net.h
19
+++ b/include/net/net.h
29
@@ -XXX,XX +XXX,XX @@ void *qemu_get_nic_opaque(NetClientState *nc);
20
@@ -XXX,XX +XXX,XX @@ typedef int (SetVnetLE)(NetClientState *, bool);
30
void qemu_del_net_client(NetClientState *nc);
21
typedef int (SetVnetBE)(NetClientState *, bool);
31
typedef void (*qemu_nic_foreach)(NICState *nic, void *opaque);
22
typedef struct SocketReadState SocketReadState;
32
void qemu_foreach_nic(qemu_nic_foreach func, void *opaque);
23
typedef void (SocketReadStateFinalize)(SocketReadState *rs);
33
+int qemu_can_receive_packet(NetClientState *nc);
24
+typedef void (NetAnnounce)(NetClientState *);
34
int qemu_can_send_packet(NetClientState *nc);
25
35
ssize_t qemu_sendv_packet(NetClientState *nc, const struct iovec *iov,
26
typedef struct NetClientInfo {
36
int iovcnt);
27
NetClientDriver type;
37
ssize_t qemu_sendv_packet_async(NetClientState *nc, const struct iovec *iov,
28
@@ -XXX,XX +XXX,XX @@ typedef struct NetClientInfo {
38
int iovcnt, NetPacketSent *sent_cb);
29
SetVnetHdrLen *set_vnet_hdr_len;
39
ssize_t qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size);
30
SetVnetLE *set_vnet_le;
40
+ssize_t qemu_receive_packet(NetClientState *nc, const uint8_t *buf, int size);
31
SetVnetBE *set_vnet_be;
41
+ssize_t qemu_receive_packet_iov(NetClientState *nc,
32
+ NetAnnounce *announce;
42
+ const struct iovec *iov,
33
} NetClientInfo;
43
+ int iovcnt);
34
44
ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size);
35
struct NetClientState {
45
ssize_t qemu_send_packet_async(NetClientState *nc, const uint8_t *buf,
36
diff --git a/net/announce.c b/net/announce.c
46
int size, NetPacketSent *sent_cb);
47
diff --git a/include/net/queue.h b/include/net/queue.h
48
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
49
--- a/include/net/queue.h
38
--- a/net/announce.c
50
+++ b/include/net/queue.h
39
+++ b/net/announce.c
51
@@ -XXX,XX +XXX,XX @@ void qemu_net_queue_append_iov(NetQueue *queue,
40
@@ -XXX,XX +XXX,XX @@ static void qemu_announce_self_iter(NICState *nic, void *opaque)
52
41
len = announce_self_create(buf, nic->conf->macaddr.a);
53
void qemu_del_net_queue(NetQueue *queue);
42
54
43
qemu_send_packet_raw(qemu_get_queue(nic), buf, len);
55
+ssize_t qemu_net_queue_receive(NetQueue *queue,
56
+ const uint8_t *data,
57
+ size_t size);
58
+
44
+
59
+ssize_t qemu_net_queue_receive_iov(NetQueue *queue,
45
+ /* if the NIC provides it's own announcement support, use it as well */
60
+ const struct iovec *iov,
46
+ if (nic->ncs->info->announce) {
61
+ int iovcnt);
47
+ nic->ncs->info->announce(nic->ncs);
62
+
48
+ }
63
ssize_t qemu_net_queue_send(NetQueue *queue,
64
NetClientState *sender,
65
unsigned flags,
66
diff --git a/net/net.c b/net/net.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/net/net.c
69
+++ b/net/net.c
70
@@ -XXX,XX +XXX,XX @@ int qemu_set_vnet_be(NetClientState *nc, bool is_be)
71
#endif
72
}
49
}
73
50
static void qemu_announce_self_once(void *opaque)
74
+int qemu_can_receive_packet(NetClientState *nc)
75
+{
76
+ if (nc->receive_disabled) {
77
+ return 0;
78
+ } else if (nc->info->can_receive &&
79
+ !nc->info->can_receive(nc)) {
80
+ return 0;
81
+ }
82
+ return 1;
83
+}
84
+
85
int qemu_can_send_packet(NetClientState *sender)
86
{
51
{
87
int vm_running = runstate_is_running();
88
@@ -XXX,XX +XXX,XX @@ int qemu_can_send_packet(NetClientState *sender)
89
return 1;
90
}
91
92
- if (sender->peer->receive_disabled) {
93
- return 0;
94
- } else if (sender->peer->info->can_receive &&
95
- !sender->peer->info->can_receive(sender->peer)) {
96
- return 0;
97
- }
98
- return 1;
99
+ return qemu_can_receive_packet(sender->peer);
100
}
101
102
static ssize_t filter_receive_iov(NetClientState *nc,
103
@@ -XXX,XX +XXX,XX @@ ssize_t qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size)
104
return qemu_send_packet_async(nc, buf, size, NULL);
105
}
106
107
+ssize_t qemu_receive_packet(NetClientState *nc, const uint8_t *buf, int size)
108
+{
109
+ if (!qemu_can_receive_packet(nc)) {
110
+ return 0;
111
+ }
112
+
113
+ return qemu_net_queue_receive(nc->incoming_queue, buf, size);
114
+}
115
+
116
+ssize_t qemu_receive_packet_iov(NetClientState *nc, const struct iovec *iov,
117
+ int iovcnt)
118
+{
119
+ if (!qemu_can_receive_packet(nc)) {
120
+ return 0;
121
+ }
122
+
123
+ return qemu_net_queue_receive_iov(nc->incoming_queue, iov, iovcnt);
124
+}
125
+
126
ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size)
127
{
128
return qemu_send_packet_async_with_flags(nc, QEMU_NET_PACKET_FLAG_RAW,
129
diff --git a/net/queue.c b/net/queue.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/net/queue.c
132
+++ b/net/queue.c
133
@@ -XXX,XX +XXX,XX @@ static ssize_t qemu_net_queue_deliver_iov(NetQueue *queue,
134
return ret;
135
}
136
137
+ssize_t qemu_net_queue_receive(NetQueue *queue,
138
+ const uint8_t *data,
139
+ size_t size)
140
+{
141
+ if (queue->delivering) {
142
+ return 0;
143
+ }
144
+
145
+ return qemu_net_queue_deliver(queue, NULL, 0, data, size);
146
+}
147
+
148
+ssize_t qemu_net_queue_receive_iov(NetQueue *queue,
149
+ const struct iovec *iov,
150
+ int iovcnt)
151
+{
152
+ if (queue->delivering) {
153
+ return 0;
154
+ }
155
+
156
+ return qemu_net_queue_deliver_iov(queue, NULL, 0, iov, iovcnt);
157
+}
158
+
159
ssize_t qemu_net_queue_send(NetQueue *queue,
160
NetClientState *sender,
161
unsigned flags,
162
--
52
--
163
2.7.4
53
2.5.0
164
54
165
55
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
2
2
3
When a network or network device is created from the command line or HMP,
3
Expose the virtio-net self announcement capability and allow
4
QemuOpts ensures that the id passes the id_wellformed check. However,
4
qemu_announce_self() to call it.
5
QMP skips this:
6
5
7
$ qemu-system-x86_64 -qmp stdio -S -nic user,id=123/456
6
These announces are caused by something external (i.e. the
8
qemu-system-x86_64: -nic user,id=123/456: Parameter id expects an identifier
7
announce-self command); they won't trigger if the migration
9
Identifiers consist of letters, digits, -, ., _, starting with a letter.
8
counter is triggering announces at the same time.
10
9
11
$ qemu-system-x86_64 -qmp stdio -S
10
Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
12
{"execute":"qmp_capabilities"}
11
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
13
{"return": {}}
12
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
14
{"execute":"netdev_add", "arguments": {"type": "user", "id": "123/456"}}
15
{"return": {}}
16
17
After:
18
19
$ qemu-system-x86_64 -qmp stdio -S
20
{"execute":"qmp_capabilities"}
21
{"return": {}}
22
{"execute":"netdev_add", "arguments": {"type": "user", "id": "123/456"}}
23
{"error": {"class": "GenericError", "desc": "Parameter "id" expects an identifier"}}
24
25
Validity checks should be performed always at the bottom of the call chain,
26
because QMP skips all the steps above. Do this for the network subsystem.
27
28
Cc: Jason Wang <jasowang@redhat.com>
29
Reviewed-by: Eric Blake <eblake@redhat.com>
30
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
31
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
Signed-off-by: Jason Wang <jasowang@redhat.com>
32
---
14
---
33
net/net.c | 12 ++++++++++++
15
hw/net/trace-events | 1 +
34
1 file changed, 12 insertions(+)
16
hw/net/virtio-net.c | 35 ++++++++++++++++++++++++++++++++---
17
2 files changed, 33 insertions(+), 3 deletions(-)
35
18
36
diff --git a/net/net.c b/net/net.c
19
diff --git a/hw/net/trace-events b/hw/net/trace-events
37
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
38
--- a/net/net.c
21
--- a/hw/net/trace-events
39
+++ b/net/net.c
22
+++ b/hw/net/trace-events
40
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@ sunhme_rx_desc(uint32_t addr, int offset, uint32_t status, int len, int cr, int
41
#include "qemu/cutils.h"
24
sunhme_rx_xsum_calc(uint16_t xsum) "calculated incoming xsum as 0x%x"
42
#include "qemu/config-file.h"
25
43
#include "qemu/ctype.h"
26
# hw/net/virtio-net.c
44
+#include "qemu/id.h"
27
+virtio_net_announce_notify(void) ""
45
#include "qemu/iov.h"
28
virtio_net_announce_timer(int round) "%d"
46
#include "qemu/qemu-print.h"
29
virtio_net_handle_announce(int round) "%d"
47
#include "qemu/main-loop.h"
30
virtio_net_post_load_device(void)
48
@@ -XXX,XX +XXX,XX @@ static int net_client_init1(const Netdev *netdev, bool is_netdev, Error **errp)
31
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
49
}
32
index XXXXXXX..XXXXXXX 100644
50
}
33
--- a/hw/net/virtio-net.c
51
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();
43
+
44
+ net->status |= VIRTIO_NET_S_ANNOUNCE;
45
+ virtio_notify_config(vdev);
46
+}
47
+
48
static void virtio_net_announce_timer(void *opaque)
49
{
50
VirtIONet *n = opaque;
51
- VirtIODevice *vdev = VIRTIO_DEVICE(n);
52
trace_virtio_net_announce_timer(n->announce_timer.round);
53
54
n->announce_timer.round--;
55
- n->status |= VIRTIO_NET_S_ANNOUNCE;
56
- virtio_notify_config(vdev);
57
+ virtio_net_announce_notify(n);
58
+}
59
+
60
+static void virtio_net_announce(NetClientState *nc)
61
+{
62
+ VirtIONet *n = qemu_get_nic_opaque(nc);
63
+ VirtIODevice *vdev = VIRTIO_DEVICE(n);
64
+
52
+ /*
65
+ /*
53
+ * The id for -net has already been checked by QemuOpts and
66
+ * Make sure the virtio migration announcement timer isn't running
54
+ * could be automatically generated, in which case it is not
67
+ * If it is, let it trigger announcement so that we do not cause
55
+ * well-formed by design. HMP and QMP only call us with
68
+ * confusion.
56
+ * is_netdev == true.
57
+ */
69
+ */
58
+ if (is_netdev && !id_wellformed(netdev->id)) {
70
+ if (n->announce_timer.round) {
59
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "id", "an identifier");
71
+ return;
60
+ return -1;
61
+ }
72
+ }
62
+
73
+
63
nc = qemu_find_netdev(netdev->id);
74
+ if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_GUEST_ANNOUNCE) &&
64
if (nc) {
75
+ virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) {
65
error_setg(errp, "Duplicate ID '%s'", netdev->id);
76
+ virtio_net_announce_notify(n);
77
+ }
78
}
79
80
static void virtio_net_vhost_status(VirtIONet *n, uint8_t status)
81
@@ -XXX,XX +XXX,XX @@ static NetClientInfo net_virtio_info = {
82
.receive = virtio_net_receive,
83
.link_status_changed = virtio_net_set_link_status,
84
.query_rx_filter = virtio_net_query_rxfilter,
85
+ .announce = virtio_net_announce,
86
};
87
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
/*
66
--
97
--
67
2.7.4
98
2.5.0
68
99
69
100
diff view generated by jsdifflib
Deleted patch
1
This patch switches to use qemu_receive_packet() which can detect
2
reentrancy and return early.
3
1
4
This is intended to address CVE-2021-3416.
5
6
Cc: Prasad J Pandit <ppandit@redhat.com>
7
Cc: qemu-stable@nongnu.org
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
11
hw/net/e1000.c | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
13
14
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/net/e1000.c
17
+++ b/hw/net/e1000.c
18
@@ -XXX,XX +XXX,XX @@ e1000_send_packet(E1000State *s, const uint8_t *buf, int size)
19
20
NetClientState *nc = qemu_get_queue(s->nic);
21
if (s->phy_reg[PHY_CTRL] & MII_CR_LOOPBACK) {
22
- nc->info->receive(nc, buf, size);
23
+ qemu_receive_packet(nc, buf, size);
24
} else {
25
qemu_send_packet(nc, buf, size);
26
}
27
--
28
2.7.4
29
30
diff view generated by jsdifflib
Deleted patch
1
This patch switches to use qemu_receive_packet() which can detect
2
reentrancy and return early.
3
1
4
This is intended to address CVE-2021-3416.
5
6
Cc: Prasad J Pandit <ppandit@redhat.com>
7
Cc: qemu-stable@nongnu.org
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
11
hw/net/dp8393x.c | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
13
14
diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/net/dp8393x.c
17
+++ b/hw/net/dp8393x.c
18
@@ -XXX,XX +XXX,XX @@ static void dp8393x_do_transmit_packets(dp8393xState *s)
19
s->regs[SONIC_TCR] |= SONIC_TCR_CRSL;
20
if (nc->info->can_receive(nc)) {
21
s->loopback_packet = 1;
22
- nc->info->receive(nc, s->tx_buffer, tx_len);
23
+ qemu_receive_packet(nc, s->tx_buffer, tx_len);
24
}
25
} else {
26
/* Transmit packet */
27
--
28
2.7.4
29
30
diff view generated by jsdifflib
1
This patch switches to use qemu_receive_receive_iov() which can detect
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
2
reentrancy and return early.
3
2
4
This is intended to address CVE-2021-3416.
3
Add a qmp command that can trigger guest announcements.
5
4
6
Cc: Prasad J Pandit <ppandit@redhat.com>
5
It uses its own announce-timer instance, and parameters
7
Cc: qemu-stable@nongnu.org
6
passed to it explicitly in the command.
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
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>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
16
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
17
---
11
hw/net/net_tx_pkt.c | 2 +-
18
net/announce.c | 7 +++++++
12
1 file changed, 1 insertion(+), 1 deletion(-)
19
qapi/net.json | 20 ++++++++++++++++++++
20
2 files changed, 27 insertions(+)
13
21
14
diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c
22
diff --git a/net/announce.c b/net/announce.c
15
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/net/net_tx_pkt.c
24
--- a/net/announce.c
17
+++ b/hw/net/net_tx_pkt.c
25
+++ b/net/announce.c
18
@@ -XXX,XX +XXX,XX @@ static inline void net_tx_pkt_sendv(struct NetTxPkt *pkt,
26
@@ -XXX,XX +XXX,XX @@
19
NetClientState *nc, const struct iovec *iov, int iov_cnt)
27
#include "net/net.h"
20
{
28
#include "qapi/clone-visitor.h"
21
if (pkt->is_loopback) {
29
#include "qapi/qapi-visit-net.h"
22
- nc->info->receive_iov(nc, iov, iov_cnt);
30
+#include "qapi/qapi-commands-net.h"
23
+ qemu_receive_packet_iov(nc, iov, iov_cnt);
31
#include "trace.h"
24
} else {
32
25
qemu_sendv_packet(nc, iov, iov_cnt);
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);
26
}
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'}
27
--
72
--
28
2.7.4
73
2.5.0
29
74
30
75
diff view generated by jsdifflib
1
This patch switches to use qemu_receive_packet() which can detect
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
2
reentrancy and return early.
3
2
4
This is intended to address CVE-2021-3416.
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.
5
6
6
Cc: Prasad J Pandit <ppandit@redhat.com>
7
Signend-off-by: Vladislav Yasevich <vyasevic@redhat.com>
7
Cc: qemu-stable@nongnu.org
8
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
8
Reviewed-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
9
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
11
---
13
hw/net/sungem.c | 2 +-
12
hmp-commands.hx | 16 ++++++++++++++++
14
1 file changed, 1 insertion(+), 1 deletion(-)
13
hmp.c | 5 +++++
14
hmp.h | 1 +
15
tests/test-hmp.c | 1 +
16
4 files changed, 23 insertions(+)
15
17
16
diff --git a/hw/net/sungem.c b/hw/net/sungem.c
18
diff --git a/hmp-commands.hx b/hmp-commands.hx
17
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/net/sungem.c
20
--- a/hmp-commands.hx
19
+++ b/hw/net/sungem.c
21
+++ b/hmp-commands.hx
20
@@ -XXX,XX +XXX,XX @@ static void sungem_send_packet(SunGEMState *s, const uint8_t *buf,
22
@@ -XXX,XX +XXX,XX @@ stops because the size limit is reached.
21
NetClientState *nc = qemu_get_queue(s->nic);
23
ETEXI
22
24
23
if (s->macregs[MAC_XIFCFG >> 2] & MAC_XIFCFG_LBCK) {
25
{
24
- nc->info->receive(nc, buf, size);
26
+ .name = "announce_self",
25
+ qemu_receive_packet(nc, buf, size);
27
+ .args_type = "",
26
} else {
28
+ .params = "",
27
qemu_send_packet(nc, buf, size);
29
+ .help = "Trigger GARP/RARP announcements",
28
}
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",
29
--
85
--
30
2.7.4
86
2.5.0
31
87
32
88
diff view generated by jsdifflib
1
This patch switches to use qemu_receive_packet() which can detect
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
2
reentrancy and return early.
3
2
4
This is intended to address CVE-2021-3416.
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).
5
5
6
Cc: Prasad J Pandit <ppandit@redhat.com>
6
Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
7
Cc: qemu-stable@nongnu.org
7
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
10
---
11
hw/net/msf2-emac.c | 2 +-
11
tests/Makefile.include | 3 ++
12
1 file changed, 1 insertion(+), 1 deletion(-)
12
tests/test-announce-self.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++
13
2 files changed, 85 insertions(+)
14
create mode 100644 tests/test-announce-self.c
13
15
14
diff --git a/hw/net/msf2-emac.c b/hw/net/msf2-emac.c
16
diff --git a/tests/Makefile.include b/tests/Makefile.include
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/net/msf2-emac.c
18
--- a/tests/Makefile.include
17
+++ b/hw/net/msf2-emac.c
19
+++ b/tests/Makefile.include
18
@@ -XXX,XX +XXX,XX @@ static void msf2_dma_tx(MSF2EmacState *s)
20
@@ -XXX,XX +XXX,XX @@ check-qtest-i386-$(CONFIG_SLIRP) += tests/test-netfilter$(EXESUF)
19
* R_CFG1 bit 0 is set.
21
check-qtest-i386-$(CONFIG_POSIX) += tests/test-filter-mirror$(EXESUF)
20
*/
22
check-qtest-i386-$(CONFIG_RTL8139_PCI) += tests/test-filter-redirector$(EXESUF)
21
if (s->regs[R_CFG1] & R_CFG1_LB_EN_MASK) {
23
check-qtest-i386-y += tests/migration-test$(EXESUF)
22
- nc->info->receive(nc, buf, size);
24
+check-qtest-i386-y += tests/test-announce-self$(EXESUF)
23
+ qemu_receive_packet(nc, buf, size);
25
check-qtest-i386-y += tests/test-x86-cpuid-compat$(EXESUF)
24
} else {
26
check-qtest-i386-y += tests/numa-test$(EXESUF)
25
qemu_send_packet(nc, buf, size);
27
check-qtest-x86_64-y += $(check-qtest-i386-y)
26
}
28
@@ -XXX,XX +XXX,XX @@ check-qtest-ppc64-$(CONFIG_PSERIES) += tests/spapr-phb-test$(EXESUF)
29
check-qtest-ppc64-$(CONFIG_PSERIES) += tests/device-plug-test$(EXESUF)
30
check-qtest-ppc64-$(CONFIG_POWERNV) += tests/pnv-xscom-test$(EXESUF)
31
check-qtest-ppc64-y += tests/migration-test$(EXESUF)
32
+check-qtest-ppc64-y += tests/test-announce-self$(EXESUF)
33
check-qtest-ppc64-$(CONFIG_PSERIES) += tests/rtas-test$(EXESUF)
34
check-qtest-ppc64-$(CONFIG_SLIRP) += tests/pxe-test$(EXESUF)
35
check-qtest-ppc64-$(CONFIG_USB_OHCI) += tests/usb-hcd-ohci-test$(EXESUF)
36
@@ -XXX,XX +XXX,XX @@ tests/usb-hcd-ehci-test$(EXESUF): tests/usb-hcd-ehci-test.o $(libqos-usb-obj-y)
37
tests/usb-hcd-xhci-test$(EXESUF): tests/usb-hcd-xhci-test.o $(libqos-usb-obj-y)
38
tests/cpu-plug-test$(EXESUF): tests/cpu-plug-test.o
39
tests/migration-test$(EXESUF): tests/migration-test.o
40
+tests/test-announce-self$(EXESUF): tests/test-announce-self.o
41
tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o $(test-util-obj-y) \
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
+ */
59
+
60
+#include "qemu/osdep.h"
61
+#include "libqtest.h"
62
+#include "qapi/qmp/qdict.h"
63
+#include "qemu-common.h"
64
+#include "qemu/sockets.h"
65
+#include "qemu/iov.h"
66
+#include "libqos/libqos-pc.h"
67
+#include "libqos/libqos-spapr.h"
68
+
69
+#ifndef ETH_P_RARP
70
+#define ETH_P_RARP 0x8035
71
+#endif
72
+
73
+static QTestState *test_init(int socket)
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
+}
27
--
132
--
28
2.7.4
133
2.5.0
29
134
30
135
diff view generated by jsdifflib