1
The following changes since commit 17783ac828adc694d986698d2d7014aedfeb48c6:
1
The following changes since commit 673205379fb499d2b72f2985b47ec7114282f5fe:
2
2
3
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.9-20170303' into staging (2017-03-04 16:31:14 +0000)
3
Merge remote-tracking branch 'remotes/philmd-gitlab/tags/python-next-20200714' into staging (2020-07-15 13:04:27 +0100)
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 f0aabd5c4ae11fde704d138e8f06c69e5c902a16:
9
for you to fetch changes up to a134321ef676723768973537bb9b49365ae2062e:
10
10
11
net/filter-mirror: Follow CODING_STYLE (2017-03-06 11:46:02 +0800)
11
ftgmac100: fix dblac write test (2020-07-15 21:00:13 +0800)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Preview pull does not reach list.
15
14
16
- fix vlan issues for e1000e
17
- convert to use vmstate for vmxnet3
18
- several fixes for colo
19
----------------------------------------------------------------
15
----------------------------------------------------------------
20
Dmitry Fleytman (5):
16
Andrew (1):
21
eth: Extend vlan stripping functions
17
hw/net: Added CSO for IPv6
22
NetRxPkt: Fix memory corruption on VLAN header stripping
23
NetRxPkt: Do not try to pull more data than present
24
NetRxPkt: Account buffer with ETH header in IOV length
25
NetRxPkt: Remove code duplication in net_rx_pkt_pull_data()
26
18
27
Dr. David Alan Gilbert (2):
19
Daniel P. Berrangé (1):
28
vmxnet3: Convert ring values to uint32_t's
20
net: detect errors from probing vnet hdr flag for TAP devices
29
vmxnet3: VMStatify rx/tx q_descr and int_state
30
21
31
Fam Zheng (1):
22
Juan Quintela (1):
32
net: Remove useless local var pkt
23
virtio-net: fix removal of failover device
33
24
34
Zhang Chen (5):
25
Laurent Vivier (1):
35
net/colo-compare: Fix memory free error
26
net: check if the file descriptor is valid before using it
36
COLO-compare: Rename compare function and remove duplicate codes
37
COLO-compare: Optimize compare_common and compare_tcp
38
COLO-compare: Fix icmp and udp compare different packet always dump bug
39
net/filter-mirror: Follow CODING_STYLE
40
27
41
zhanghailiang (6):
28
Zhang Chen (2):
42
colo-compare: use g_timeout_source_new() to process the stale packets
29
net/colo-compare.c: Expose compare "max_queue_size" to users
43
colo-compare: kick compare thread to exit after some cleanup in finalization
30
qemu-options.hx: Clean up and fix typo for colo-compare
44
char: remove the right fd been watched in qemu_chr_fe_set_handlers()
45
colo-compare: Fix removing fds been watched incorrectly in finalization
46
net/colo: fix memory double free error
47
filter-rewriter: skip net_checksum_calculate() while offset = 0
48
31
49
chardev/char-fd.c | 6 +-
32
erik-smit (1):
50
chardev/char-io.c | 8 +-
33
ftgmac100: fix dblac write test
51
chardev/char-io.h | 2 +-
34
52
chardev/char-pty.c | 2 +-
35
hw/net/ftgmac100.c | 14 +++++++------
53
chardev/char-socket.c | 4 +-
36
hw/net/net_tx_pkt.c | 15 ++++++++++---
54
chardev/char-udp.c | 6 +-
37
hw/net/virtio-net.c | 1 +
55
chardev/char.c | 2 +-
38
include/qemu/sockets.h | 1 +
56
hw/net/net_rx_pkt.c | 41 ++++----
39
net/colo-compare.c | 43 ++++++++++++++++++++++++++++++++++++-
57
hw/net/vmxnet3.c | 284 +++++++++++++++++---------------------------------
40
net/socket.c | 9 ++++++--
58
include/net/eth.h | 4 +-
41
net/tap-bsd.c | 2 +-
59
net/colo-compare.c | 189 +++++++++++++++++++--------------
42
net/tap-linux.c | 8 ++++---
60
net/colo.c | 4 +-
43
net/tap-solaris.c | 2 +-
61
net/eth.c | 25 +++--
44
net/tap-stub.c | 2 +-
62
net/filter-mirror.c | 7 +-
45
net/tap.c | 50 +++++++++++++++++++++++++++++++++++--------
63
net/filter-rewriter.c | 17 +--
46
net/tap_int.h | 2 +-
64
15 files changed, 273 insertions(+), 328 deletions(-)
47
qemu-options.hx | 33 +++++++++++++++--------------
48
util/oslib-posix.c | 26 ++++++++++++++++-------
49
util/oslib-win32.c | 57 ++++++++++++++++++++++++++++----------------------
50
15 files changed, 188 insertions(+), 77 deletions(-)
65
51
66
52
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
This has been pointless since commit 605d52e62, which was a
4
search-and-replace, overlooked the redundancy.
5
6
Signed-off-by: Fam Zheng <famz@redhat.com>
7
Reviewed-by: Dmitry Fleytman <dmitry@daynix.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
10
hw/net/net_rx_pkt.c | 1 -
11
1 file changed, 1 deletion(-)
12
13
diff --git a/hw/net/net_rx_pkt.c b/hw/net/net_rx_pkt.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/net/net_rx_pkt.c
16
+++ b/hw/net/net_rx_pkt.c
17
@@ -XXX,XX +XXX,XX @@ void net_rx_pkt_attach_iovec_ex(struct NetRxPkt *pkt,
18
void net_rx_pkt_dump(struct NetRxPkt *pkt)
19
{
20
#ifdef NET_RX_PKT_DEBUG
21
- NetRxPkt *pkt = (NetRxPkt *)pkt;
22
assert(pkt);
23
24
printf("RX PKT: tot_len: %d, vlan_stripped: %d, vlan_tag: %d\n",
25
--
26
2.7.4
27
28
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Juan Quintela <quintela@redhat.com>
2
2
3
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
3
If you have a networking device and its virtio failover device, and
4
you remove them in this order:
5
- virtio device
6
- the real device
7
8
You get qemu crash.
9
See bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1820120
10
11
Bug exist on qemu 4.2 and 5.0.
12
But in 5.0 don't shows because commit
13
77b06bba62034a87cc61a9c8de1309ae3e527d97
14
15
somehow papers over it.
16
17
CC: Jason Wang <jasowang@redhat.com>
18
CC: Michael S. Tsirkin <mst@redhat.com>
19
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
20
Acked-by: Laurent Vivier <lvivier@redhat.com>
21
Signed-off-by: Juan Quintela <quintela@redhat.com>
4
Signed-off-by: Jason Wang <jasowang@redhat.com>
22
Signed-off-by: Jason Wang <jasowang@redhat.com>
5
---
23
---
6
net/filter-mirror.c | 7 ++++---
24
hw/net/virtio-net.c | 1 +
7
1 file changed, 4 insertions(+), 3 deletions(-)
25
1 file changed, 1 insertion(+)
8
26
9
diff --git a/net/filter-mirror.c b/net/filter-mirror.c
27
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
10
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
11
--- a/net/filter-mirror.c
29
--- a/hw/net/virtio-net.c
12
+++ b/net/filter-mirror.c
30
+++ b/hw/net/virtio-net.c
13
@@ -XXX,XX +XXX,XX @@ static int filter_mirror_send(CharBackend *chr_out,
31
@@ -XXX,XX +XXX,XX @@ static void virtio_net_device_unrealize(DeviceState *dev)
14
{
32
g_free(n->vlans);
15
int ret = 0;
33
16
ssize_t size = 0;
34
if (n->failover) {
17
- uint32_t len = 0;
35
+ device_listener_unregister(&n->primary_listener);
18
+ uint32_t len = 0;
36
g_free(n->primary_device_id);
19
char *buf;
37
g_free(n->standby_id);
20
38
qobject_unref(n->primary_device_dict);
21
size = iov_size(iov, iovcnt);
22
@@ -XXX,XX +XXX,XX @@ err:
23
return ret < 0 ? ret : -EIO;
24
}
25
26
-static void
27
-redirector_to_filter(NetFilterState *nf, const uint8_t *buf, int len)
28
+static void redirector_to_filter(NetFilterState *nf,
29
+ const uint8_t *buf,
30
+ int len)
31
{
32
struct iovec iov = {
33
.iov_base = (void *)buf,
34
--
39
--
35
2.7.4
40
2.5.0
36
41
37
42
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Andrew <andrew@daynix.com>
2
2
3
Add offset args for colo_packet_compare_common, optimize
3
Added fix for checksum offload for IPv6 if a backend doesn't
4
colo_packet_compare_icmp() and colo_packet_compare_udp()
4
have a virtual header.
5
just compare the IP payload. Before compare all tcp packet,
5
This patch is a part of IPv6 fragmentation.
6
we compare tcp checksum firstly, this function can get
7
better performance.
8
6
9
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
7
Signed-off-by: Andrew Melnychenko <andrew@daynix.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
---
9
---
12
net/colo-compare.c | 50 ++++++++++++++++++++++++++++++++++++--------------
10
hw/net/net_tx_pkt.c | 15 ++++++++++++---
13
1 file changed, 36 insertions(+), 14 deletions(-)
11
1 file changed, 12 insertions(+), 3 deletions(-)
14
12
15
diff --git a/net/colo-compare.c b/net/colo-compare.c
13
diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c
16
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
17
--- a/net/colo-compare.c
15
--- a/hw/net/net_tx_pkt.c
18
+++ b/net/colo-compare.c
16
+++ b/hw/net/net_tx_pkt.c
19
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode)
17
@@ -XXX,XX +XXX,XX @@ static void net_tx_pkt_do_sw_csum(struct NetTxPkt *pkt)
20
* return: 0 means packet same
18
/* num of iovec without vhdr */
21
* > 0 || < 0 means packet different
19
uint32_t iov_len = pkt->payload_frags + NET_TX_PKT_PL_START_FRAG - 1;
22
*/
20
uint16_t csl;
23
-static int colo_packet_compare_common(Packet *ppkt, Packet *spkt)
21
- struct ip_header *iphdr;
24
+static int colo_packet_compare_common(Packet *ppkt, Packet *spkt, int offset)
22
size_t csum_offset = pkt->virt_hdr.csum_start + pkt->virt_hdr.csum_offset;
25
{
23
+ uint16_t l3_proto = eth_get_l3_proto(iov, 1, iov->iov_len);
26
trace_colo_compare_ip_info(ppkt->size, inet_ntoa(ppkt->ip->ip_src),
24
27
inet_ntoa(ppkt->ip->ip_dst), spkt->size,
25
/* Put zero to checksum field */
28
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_common(Packet *ppkt, Packet *spkt)
26
iov_from_buf(iov, iov_len, csum_offset, &csum, sizeof csum);
29
inet_ntoa(spkt->ip->ip_dst));
27
@@ -XXX,XX +XXX,XX @@ static void net_tx_pkt_do_sw_csum(struct NetTxPkt *pkt)
30
28
/* Calculate L4 TCP/UDP checksum */
31
if (ppkt->size == spkt->size) {
29
csl = pkt->payload_len;
32
- return memcmp(ppkt->data, spkt->data, spkt->size);
30
33
+ return memcmp(ppkt->data + offset, spkt->data + offset,
31
+ csum_cntr = 0;
34
+ spkt->size - offset);
32
+ cso = 0;
35
} else {
33
/* add pseudo header to csum */
36
trace_colo_compare_main("Net packet size are not the same");
34
- iphdr = pkt->vec[NET_TX_PKT_L3HDR_FRAG].iov_base;
37
return -1;
35
- csum_cntr = eth_calc_ip4_pseudo_hdr_csum(iphdr, csl, &cso);
38
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_tcp(Packet *spkt, Packet *ppkt)
36
+ if (l3_proto == ETH_P_IP) {
39
37
+ csum_cntr = eth_calc_ip4_pseudo_hdr_csum(
40
trace_colo_compare_main("compare tcp");
38
+ pkt->vec[NET_TX_PKT_L3HDR_FRAG].iov_base,
41
39
+ csl, &cso);
42
- if (ppkt->size != spkt->size) {
40
+ } else if (l3_proto == ETH_P_IPV6) {
43
- if (trace_event_get_state(TRACE_COLO_COMPARE_MISCOMPARE)) {
41
+ csum_cntr = eth_calc_ip6_pseudo_hdr_csum(
44
- trace_colo_compare_main("pkt size not same");
42
+ pkt->vec[NET_TX_PKT_L3HDR_FRAG].iov_base,
45
- }
43
+ csl, pkt->l4proto, &cso);
46
- return -1;
47
- }
48
-
49
ptcp = (struct tcphdr *)ppkt->transport_header;
50
stcp = (struct tcphdr *)spkt->transport_header;
51
52
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_tcp(Packet *spkt, Packet *ppkt)
53
spkt->ip->ip_sum = ppkt->ip->ip_sum;
54
}
55
56
- res = memcmp(ppkt->data + ETH_HLEN, spkt->data + ETH_HLEN,
57
- (spkt->size - ETH_HLEN));
58
+ if (ptcp->th_sum == stcp->th_sum) {
59
+ res = colo_packet_compare_common(ppkt, spkt, ETH_HLEN);
60
+ } else {
61
+ res = -1;
62
+ }
44
+ }
63
45
64
if (res != 0 && trace_event_get_state(TRACE_COLO_COMPARE_MISCOMPARE)) {
46
/* data checksum */
65
trace_colo_compare_pkt_info_src(inet_ntoa(ppkt->ip->ip_src),
47
csum_cntr +=
66
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_tcp(Packet *spkt, Packet *ppkt)
67
static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt)
68
{
69
int ret;
70
+ int network_header_length = ppkt->ip->ip_hl * 4;
71
72
trace_colo_compare_main("compare udp");
73
74
- ret = colo_packet_compare_common(ppkt, spkt);
75
+ /*
76
+ * Because of ppkt and spkt are both in the same connection,
77
+ * The ppkt's src ip, dst ip, src port, dst port, ip_proto all are
78
+ * same with spkt. In addition, IP header's Identification is a random
79
+ * field, we can handle it in IP fragmentation function later.
80
+ * COLO just concern the response net packet payload from primary guest
81
+ * and secondary guest are same or not, So we ignored all IP header include
82
+ * other field like TOS,TTL,IP Checksum. we only need to compare
83
+ * the ip payload here.
84
+ */
85
+ ret = colo_packet_compare_common(ppkt, spkt,
86
+ network_header_length + ETH_HLEN);
87
88
if (ret) {
89
trace_colo_compare_udp_miscompare("primary pkt size", ppkt->size);
90
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt)
91
*/
92
static int colo_packet_compare_icmp(Packet *spkt, Packet *ppkt)
93
{
94
+ int network_header_length = ppkt->ip->ip_hl * 4;
95
+
96
trace_colo_compare_main("compare icmp");
97
98
- if (colo_packet_compare_common(ppkt, spkt)) {
99
+ /*
100
+ * Because of ppkt and spkt are both in the same connection,
101
+ * The ppkt's src ip, dst ip, src port, dst port, ip_proto all are
102
+ * same with spkt. In addition, IP header's Identification is a random
103
+ * field, we can handle it in IP fragmentation function later.
104
+ * COLO just concern the response net packet payload from primary guest
105
+ * and secondary guest are same or not, So we ignored all IP header include
106
+ * other field like TOS,TTL,IP Checksum. we only need to compare
107
+ * the ip payload here.
108
+ */
109
+ if (colo_packet_compare_common(ppkt, spkt,
110
+ network_header_length + ETH_HLEN)) {
111
trace_colo_compare_icmp_miscompare("primary pkt size",
112
ppkt->size);
113
qemu_hexdump((char *)ppkt->data, stderr, "colo-compare",
114
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_other(Packet *spkt, Packet *ppkt)
115
inet_ntoa(ppkt->ip->ip_dst), spkt->size,
116
inet_ntoa(spkt->ip->ip_src),
117
inet_ntoa(spkt->ip->ip_dst));
118
- return colo_packet_compare_common(ppkt, spkt);
119
+ return colo_packet_compare_common(ppkt, spkt, 0);
120
}
121
122
static int colo_old_packet_check_one(Packet *pkt, int64_t *check_time)
123
--
48
--
124
2.7.4
49
2.5.0
125
50
126
51
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Zhang Chen <chen.zhang@intel.com>
2
2
3
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
3
This patch allow users to set the "max_queue_size" according
4
to their environment.
5
6
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
4
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
5
---
8
---
6
net/colo-compare.c | 18 ++++++++++++------
9
net/colo-compare.c | 43 ++++++++++++++++++++++++++++++++++++++++++-
7
1 file changed, 12 insertions(+), 6 deletions(-)
10
qemu-options.hx | 5 +++--
11
2 files changed, 45 insertions(+), 3 deletions(-)
8
12
9
diff --git a/net/colo-compare.c b/net/colo-compare.c
13
diff --git a/net/colo-compare.c b/net/colo-compare.c
10
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
11
--- a/net/colo-compare.c
15
--- a/net/colo-compare.c
12
+++ b/net/colo-compare.c
16
+++ b/net/colo-compare.c
13
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt)
17
@@ -XXX,XX +XXX,XX @@ static bool colo_compare_active;
14
18
static QemuMutex event_mtx;
15
if (ret) {
19
static QemuCond event_complete_cond;
16
trace_colo_compare_udp_miscompare("primary pkt size", ppkt->size);
20
static int event_unhandled_count;
17
- qemu_hexdump((char *)ppkt->data, stderr, "colo-compare", ppkt->size);
21
+static uint32_t max_queue_size;
18
trace_colo_compare_udp_miscompare("Secondary pkt size", spkt->size);
22
19
- qemu_hexdump((char *)spkt->data, stderr, "colo-compare", spkt->size);
23
/*
20
+ if (trace_event_get_state(TRACE_COLO_COMPARE_MISCOMPARE)) {
24
* + CompareState ++
21
+ qemu_hexdump((char *)ppkt->data, stderr, "colo-compare pri pkt",
25
@@ -XXX,XX +XXX,XX @@ static void fill_pkt_tcp_info(void *data, uint32_t *max_ack)
22
+ ppkt->size);
26
*/
23
+ qemu_hexdump((char *)spkt->data, stderr, "colo-compare sec pkt",
27
static int colo_insert_packet(GQueue *queue, Packet *pkt, uint32_t *max_ack)
24
+ spkt->size);
28
{
25
+ }
29
- if (g_queue_get_length(queue) <= MAX_QUEUE_SIZE) {
30
+ if (g_queue_get_length(queue) <= max_queue_size) {
31
if (pkt->ip->ip_p == IPPROTO_TCP) {
32
fill_pkt_tcp_info(pkt, max_ack);
33
g_queue_insert_sorted(queue,
34
@@ -XXX,XX +XXX,XX @@ static void compare_set_expired_scan_cycle(Object *obj, Visitor *v,
35
s->expired_scan_cycle = value;
36
}
37
38
+static void get_max_queue_size(Object *obj, Visitor *v,
39
+ const char *name, void *opaque,
40
+ Error **errp)
41
+{
42
+ uint32_t value = max_queue_size;
43
+
44
+ visit_type_uint32(v, name, &value, errp);
45
+}
46
+
47
+static void set_max_queue_size(Object *obj, Visitor *v,
48
+ const char *name, void *opaque,
49
+ Error **errp)
50
+{
51
+ Error *local_err = NULL;
52
+ uint32_t value;
53
+
54
+ visit_type_uint32(v, name, &value, &local_err);
55
+ if (local_err) {
56
+ goto out;
57
+ }
58
+ if (!value) {
59
+ error_setg(&local_err, "Property '%s.%s' requires a positive value",
60
+ object_get_typename(obj), name);
61
+ goto out;
62
+ }
63
+ max_queue_size = value;
64
+
65
+out:
66
+ error_propagate(errp, local_err);
67
+}
68
+
69
static void compare_pri_rs_finalize(SocketReadState *pri_rs)
70
{
71
CompareState *s = container_of(pri_rs, CompareState, pri_rs);
72
@@ -XXX,XX +XXX,XX @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
73
s->expired_scan_cycle = REGULAR_PACKET_CHECK_MS;
26
}
74
}
27
75
28
return ret;
76
+ if (!max_queue_size) {
29
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_icmp(Packet *spkt, Packet *ppkt)
77
+ /* Set default queue size to 1024 */
30
network_header_length + ETH_HLEN)) {
78
+ max_queue_size = MAX_QUEUE_SIZE;
31
trace_colo_compare_icmp_miscompare("primary pkt size",
79
+ }
32
ppkt->size);
80
+
33
- qemu_hexdump((char *)ppkt->data, stderr, "colo-compare",
81
if (find_and_check_chardev(&chr, s->pri_indev, errp) ||
34
- ppkt->size);
82
!qemu_chr_fe_init(&s->chr_pri_in, chr, errp)) {
35
trace_colo_compare_icmp_miscompare("Secondary pkt size",
83
return;
36
spkt->size);
84
@@ -XXX,XX +XXX,XX @@ static void colo_compare_init(Object *obj)
37
- qemu_hexdump((char *)spkt->data, stderr, "colo-compare",
85
compare_get_expired_scan_cycle,
38
- spkt->size);
86
compare_set_expired_scan_cycle, NULL, NULL);
39
+ if (trace_event_get_state(TRACE_COLO_COMPARE_MISCOMPARE)) {
87
40
+ qemu_hexdump((char *)ppkt->data, stderr, "colo-compare pri pkt",
88
+ object_property_add(obj, "max_queue_size", "uint32",
41
+ ppkt->size);
89
+ get_max_queue_size,
42
+ qemu_hexdump((char *)spkt->data, stderr, "colo-compare sec pkt",
90
+ set_max_queue_size, NULL, NULL);
43
+ spkt->size);
91
+
44
+ }
92
s->vnet_hdr = false;
45
return -1;
93
object_property_add_bool(obj, "vnet_hdr_support", compare_get_vnet_hdr,
46
} else {
94
compare_set_vnet_hdr);
47
return 0;
95
diff --git a/qemu-options.hx b/qemu-options.hx
96
index XXXXXXX..XXXXXXX 100644
97
--- a/qemu-options.hx
98
+++ b/qemu-options.hx
99
@@ -XXX,XX +XXX,XX @@ SRST
100
stored. The file format is libpcap, so it can be analyzed with
101
tools such as tcpdump or Wireshark.
102
103
- ``-object colo-compare,id=id,primary_in=chardevid,secondary_in=chardevid,outdev=chardevid,iothread=id[,vnet_hdr_support][,notify_dev=id][,compare_timeout=@var{ms}][,expired_scan_cycle=@var{ms}``
104
+ ``-object colo-compare,id=id,primary_in=chardevid,secondary_in=chardevid,outdev=chardevid,iothread=id[,vnet_hdr_support][,notify_dev=id][,compare_timeout=@var{ms}][,expired_scan_cycle=@var{ms}][,max_queue_size=@var{size}]``
105
Colo-compare gets packet from primary\_inchardevid and
106
secondary\_inchardevid, than compare primary packet with
107
secondary packet. If the packets are same, we will output
108
@@ -XXX,XX +XXX,XX @@ SRST
109
vnet\_hdr\_len. Then compare\_timeout=@var{ms} determines the
110
maximum delay colo-compare wait for the packet.
111
The expired\_scan\_cycle=@var{ms} to set the period of scanning
112
- expired primary node network packets.
113
+ expired primary node network packets. The max\_queue\_size=@var{size}
114
+ is to set the max compare queue size depend on user environment.
115
If you want to use Xen COLO, will need the notify\_dev to
116
notify Xen colo-frame to do checkpoint.
117
48
--
118
--
49
2.7.4
119
2.5.0
50
120
51
121
diff view generated by jsdifflib
1
From: zhanghailiang <zhang.zhanghailiang@huawei.com>
1
From: Zhang Chen <chen.zhang@intel.com>
2
2
3
The 'primary_list' and 'secondary_list' members of struct Connection
3
Fix some typo and optimized some descriptions.
4
is not allocated through dynamically g_queue_new(), but we free it by using
5
g_queue_free(), which will lead to a double-free bug.
6
4
7
Reviewed-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
5
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
8
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
7
---
11
net/colo.c | 4 ++--
8
qemu-options.hx | 32 ++++++++++++++++----------------
12
1 file changed, 2 insertions(+), 2 deletions(-)
9
1 file changed, 16 insertions(+), 16 deletions(-)
13
10
14
diff --git a/net/colo.c b/net/colo.c
11
diff --git a/qemu-options.hx b/qemu-options.hx
15
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
16
--- a/net/colo.c
13
--- a/qemu-options.hx
17
+++ b/net/colo.c
14
+++ b/qemu-options.hx
18
@@ -XXX,XX +XXX,XX @@ void connection_destroy(void *opaque)
15
@@ -XXX,XX +XXX,XX @@ SRST
19
Connection *conn = opaque;
16
tools such as tcpdump or Wireshark.
20
17
21
g_queue_foreach(&conn->primary_list, packet_destroy, NULL);
18
``-object colo-compare,id=id,primary_in=chardevid,secondary_in=chardevid,outdev=chardevid,iothread=id[,vnet_hdr_support][,notify_dev=id][,compare_timeout=@var{ms}][,expired_scan_cycle=@var{ms}][,max_queue_size=@var{size}]``
22
- g_queue_free(&conn->primary_list);
19
- Colo-compare gets packet from primary\_inchardevid and
23
+ g_queue_clear(&conn->primary_list);
20
- secondary\_inchardevid, than compare primary packet with
24
g_queue_foreach(&conn->secondary_list, packet_destroy, NULL);
21
- secondary packet. If the packets are same, we will output
25
- g_queue_free(&conn->secondary_list);
22
- primary packet to outdevchardevid, else we will notify
26
+ g_queue_clear(&conn->secondary_list);
23
- colo-frame do checkpoint and send primary packet to
27
g_slice_free(Connection, conn);
24
- outdevchardevid. In order to improve efficiency, we need to put
28
}
25
- the task of comparison in another thread. If it has the
26
- vnet\_hdr\_support flag, colo compare will send/recv packet with
27
- vnet\_hdr\_len. Then compare\_timeout=@var{ms} determines the
28
- maximum delay colo-compare wait for the packet.
29
- The expired\_scan\_cycle=@var{ms} to set the period of scanning
30
- expired primary node network packets. The max\_queue\_size=@var{size}
31
- is to set the max compare queue size depend on user environment.
32
- If you want to use Xen COLO, will need the notify\_dev to
33
+ Colo-compare gets packet from primary\_in chardevid and
34
+ secondary\_in, then compare whether the payload of primary packet
35
+ and secondary packet are the same. If same, it will output
36
+ primary packet to out\_dev, else it will notify COLO-framework to do
37
+ checkpoint and send primary packet to out\_dev. In order to
38
+ improve efficiency, we need to put the task of comparison in
39
+ another iothread. If it has the vnet\_hdr\_support flag,
40
+ colo compare will send/recv packet with vnet\_hdr\_len.
41
+ The compare\_timeout=@var{ms} determines the maximum time of the
42
+ colo-compare hold the packet. The expired\_scan\_cycle=@var{ms}
43
+ is to set the period of scanning expired primary node network packets.
44
+ The max\_queue\_size=@var{size} is to set the max compare queue
45
+ size depend on user environment.
46
+ If user want to use Xen COLO, need to add the notify\_dev to
47
notify Xen colo-frame to do checkpoint.
48
49
- we must use it with the help of filter-mirror and
50
- filter-redirector.
51
+ COLO-compare must be used with the help of filter-mirror,
52
+ filter-redirector and filter-rewriter.
53
54
::
29
55
30
--
56
--
31
2.7.4
57
2.5.0
32
58
33
59
diff view generated by jsdifflib
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
1
From: Laurent Vivier <lvivier@redhat.com>
2
2
3
Fairly simple mechanical conversion of all fields.
3
qemu_set_nonblock() checks that the file descriptor can be used and, if
4
4
not, crashes QEMU. An assert() is used for that. The use of assert() is
5
TODO!!!!
5
used to detect programming error and the coredump will allow to debug
6
The problem is vmxnet3-ring size/cell_size/next are declared as size_t
6
the problem.
7
but written as 32bit.
7
8
8
But in the case of the tap device, this assert() can be triggered by
9
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
9
a misconfiguration by the user. At startup, it's not a real problem, but it
10
Acked-by: Dmitry Fleytman <dmitry@daynix.com>
10
can also happen during the hot-plug of a new device, and here it's a
11
problem because we can crash a perfectly healthy system.
12
13
For instance:
14
# ip link add link virbr0 name macvtap0 type macvtap mode bridge
15
# ip link set macvtap0 up
16
# TAP=/dev/tap$(ip -o link show macvtap0 | cut -d: -f1)
17
# qemu-system-x86_64 -machine q35 -device pcie-root-port,id=pcie-root-port-0 -monitor stdio 9<> $TAP
18
(qemu) netdev_add type=tap,id=hostnet0,vhost=on,fd=9
19
(qemu) device_add driver=virtio-net-pci,netdev=hostnet0,id=net0,bus=pcie-root-port-0
20
(qemu) device_del net0
21
(qemu) netdev_del hostnet0
22
(qemu) netdev_add type=tap,id=hostnet1,vhost=on,fd=9
23
qemu-system-x86_64: .../util/oslib-posix.c:247: qemu_set_nonblock: Assertion `f != -1' failed.
24
Aborted (core dumped)
25
26
To avoid that, add a function, qemu_try_set_nonblock(), that allows to report the
27
problem without crashing.
28
29
In the same way, we also update the function for vhostfd in net_init_tap_one() and
30
for fd in net_init_socket() (both descriptors are provided by the user and can
31
be wrong).
32
33
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
34
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
35
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
36
---
13
hw/net/vmxnet3.c | 272 ++++++++++++++++++-------------------------------------
37
include/qemu/sockets.h | 1 +
14
1 file changed, 90 insertions(+), 182 deletions(-)
38
net/socket.c | 9 ++++++--
15
39
net/tap.c | 25 ++++++++++++++++++----
16
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
40
util/oslib-posix.c | 26 ++++++++++++++++-------
17
index XXXXXXX..XXXXXXX 100644
41
util/oslib-win32.c | 57 ++++++++++++++++++++++++++++----------------------
18
--- a/hw/net/vmxnet3.c
42
5 files changed, 79 insertions(+), 39 deletions(-)
19
+++ b/hw/net/vmxnet3.c
43
20
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmxstate_vmxnet3_mcast_list = {
44
diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/include/qemu/sockets.h
47
+++ b/include/qemu/sockets.h
48
@@ -XXX,XX +XXX,XX @@ int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
49
int socket_set_cork(int fd, int v);
50
int socket_set_nodelay(int fd);
51
void qemu_set_block(int fd);
52
+int qemu_try_set_nonblock(int fd);
53
void qemu_set_nonblock(int fd);
54
int socket_set_fast_reuse(int fd);
55
56
diff --git a/net/socket.c b/net/socket.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/net/socket.c
59
+++ b/net/socket.c
60
@@ -XXX,XX +XXX,XX @@ int net_init_socket(const Netdev *netdev, const char *name,
21
}
61
}
22
};
62
23
63
if (sock->has_fd) {
24
-static void vmxnet3_get_ring_from_file(QEMUFile *f, Vmxnet3Ring *r)
64
- int fd;
65
+ int fd, ret;
66
67
fd = monitor_fd_param(cur_mon, sock->fd, errp);
68
if (fd == -1) {
69
return -1;
70
}
71
- qemu_set_nonblock(fd);
72
+ ret = qemu_try_set_nonblock(fd);
73
+ if (ret < 0) {
74
+ error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d",
75
+ name, fd);
76
+ return -1;
77
+ }
78
if (!net_socket_fd_init(peer, "socket", name, fd, 1, sock->mcast,
79
errp)) {
80
return -1;
81
diff --git a/net/tap.c b/net/tap.c
82
index XXXXXXX..XXXXXXX 100644
83
--- a/net/tap.c
84
+++ b/net/tap.c
85
@@ -XXX,XX +XXX,XX @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
86
}
87
88
if (vhostfdname) {
89
+ int ret;
90
+
91
vhostfd = monitor_fd_param(cur_mon, vhostfdname, &err);
92
if (vhostfd == -1) {
93
if (tap->has_vhostforce && tap->vhostforce) {
94
@@ -XXX,XX +XXX,XX @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
95
}
96
return;
97
}
98
- qemu_set_nonblock(vhostfd);
99
+ ret = qemu_try_set_nonblock(vhostfd);
100
+ if (ret < 0) {
101
+ error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d",
102
+ name, fd);
103
+ return;
104
+ }
105
} else {
106
vhostfd = open("/dev/vhost-net", O_RDWR);
107
if (vhostfd < 0) {
108
@@ -XXX,XX +XXX,XX @@ int net_init_tap(const Netdev *netdev, const char *name,
109
Error *err = NULL;
110
const char *vhostfdname;
111
char ifname[128];
112
+ int ret = 0;
113
114
assert(netdev->type == NET_CLIENT_DRIVER_TAP);
115
tap = &netdev->u.tap;
116
@@ -XXX,XX +XXX,XX @@ int net_init_tap(const Netdev *netdev, const char *name,
117
return -1;
118
}
119
120
- qemu_set_nonblock(fd);
121
+ ret = qemu_try_set_nonblock(fd);
122
+ if (ret < 0) {
123
+ error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d",
124
+ name, fd);
125
+ return -1;
126
+ }
127
128
vnet_hdr = tap_probe_vnet_hdr(fd);
129
130
@@ -XXX,XX +XXX,XX @@ int net_init_tap(const Netdev *netdev, const char *name,
131
char **fds;
132
char **vhost_fds;
133
int nfds = 0, nvhosts = 0;
134
- int ret = 0;
135
136
if (tap->has_ifname || tap->has_script || tap->has_downscript ||
137
tap->has_vnet_hdr || tap->has_helper || tap->has_queues ||
138
@@ -XXX,XX +XXX,XX @@ int net_init_tap(const Netdev *netdev, const char *name,
139
goto free_fail;
140
}
141
142
- qemu_set_nonblock(fd);
143
+ ret = qemu_try_set_nonblock(fd);
144
+ if (ret < 0) {
145
+ error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d",
146
+ name, fd);
147
+ goto free_fail;
148
+ }
149
150
if (i == 0) {
151
vnet_hdr = tap_probe_vnet_hdr(fd);
152
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
153
index XXXXXXX..XXXXXXX 100644
154
--- a/util/oslib-posix.c
155
+++ b/util/oslib-posix.c
156
@@ -XXX,XX +XXX,XX @@ void qemu_set_block(int fd)
157
assert(f != -1);
158
}
159
160
-void qemu_set_nonblock(int fd)
161
+int qemu_try_set_nonblock(int fd)
162
{
163
int f;
164
f = fcntl(fd, F_GETFL);
165
- assert(f != -1);
166
- f = fcntl(fd, F_SETFL, f | O_NONBLOCK);
167
-#ifdef __OpenBSD__
168
if (f == -1) {
169
+ return -errno;
170
+ }
171
+ if (fcntl(fd, F_SETFL, f | O_NONBLOCK) == -1) {
172
+#ifdef __OpenBSD__
173
/*
174
* Previous to OpenBSD 6.3, fcntl(F_SETFL) is not permitted on
175
* memory devices and sets errno to ENODEV.
176
* It's OK if we fail to set O_NONBLOCK on devices like /dev/null,
177
* because they will never block anyway.
178
*/
179
- assert(errno == ENODEV);
180
- }
181
-#else
182
- assert(f != -1);
183
+ if (errno == ENODEV) {
184
+ return 0;
185
+ }
186
#endif
187
+ return -errno;
188
+ }
189
+ return 0;
190
+}
191
+
192
+void qemu_set_nonblock(int fd)
193
+{
194
+ int f;
195
+ f = qemu_try_set_nonblock(fd);
196
+ assert(f == 0);
197
}
198
199
int socket_set_fast_reuse(int fd)
200
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
201
index XXXXXXX..XXXXXXX 100644
202
--- a/util/oslib-win32.c
203
+++ b/util/oslib-win32.c
204
@@ -XXX,XX +XXX,XX @@ struct tm *localtime_r(const time_t *timep, struct tm *result)
205
}
206
#endif /* CONFIG_LOCALTIME_R */
207
208
-void qemu_set_block(int fd)
25
-{
209
-{
26
- r->pa = qemu_get_be64(f);
210
- unsigned long opt = 0;
27
- r->size = qemu_get_be32(f);
211
- WSAEventSelect(fd, NULL, 0);
28
- r->cell_size = qemu_get_be32(f);
212
- ioctlsocket(fd, FIONBIO, &opt);
29
- r->next = qemu_get_be32(f);
30
- r->gen = qemu_get_byte(f);
31
-}
213
-}
32
-
214
-
33
-static void vmxnet3_put_ring_to_file(QEMUFile *f, Vmxnet3Ring *r)
215
-void qemu_set_nonblock(int fd)
34
-{
216
-{
35
- qemu_put_be64(f, r->pa);
217
- unsigned long opt = 1;
36
- qemu_put_be32(f, r->size);
218
- ioctlsocket(fd, FIONBIO, &opt);
37
- qemu_put_be32(f, r->cell_size);
219
- qemu_fd_register(fd);
38
- qemu_put_be32(f, r->next);
39
- qemu_put_byte(f, r->gen);
40
-}
220
-}
41
-
221
-
42
-static void vmxnet3_get_tx_stats_from_file(QEMUFile *f,
222
-int socket_set_fast_reuse(int fd)
43
- struct UPT1_TxStats *tx_stat)
44
-{
223
-{
45
- tx_stat->TSOPktsTxOK = qemu_get_be64(f);
224
- /* Enabling the reuse of an endpoint that was used by a socket still in
46
- tx_stat->TSOBytesTxOK = qemu_get_be64(f);
225
- * TIME_WAIT state is usually performed by setting SO_REUSEADDR. On Windows
47
- tx_stat->ucastPktsTxOK = qemu_get_be64(f);
226
- * fast reuse is the default and SO_REUSEADDR does strange things. So we
48
- tx_stat->ucastBytesTxOK = qemu_get_be64(f);
227
- * don't have to do anything here. More info can be found at:
49
- tx_stat->mcastPktsTxOK = qemu_get_be64(f);
228
- * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621.aspx */
50
- tx_stat->mcastBytesTxOK = qemu_get_be64(f);
51
- tx_stat->bcastPktsTxOK = qemu_get_be64(f);
52
- tx_stat->bcastBytesTxOK = qemu_get_be64(f);
53
- tx_stat->pktsTxError = qemu_get_be64(f);
54
- tx_stat->pktsTxDiscard = qemu_get_be64(f);
55
-}
56
-
57
-static void vmxnet3_put_tx_stats_to_file(QEMUFile *f,
58
- struct UPT1_TxStats *tx_stat)
59
-{
60
- qemu_put_be64(f, tx_stat->TSOPktsTxOK);
61
- qemu_put_be64(f, tx_stat->TSOBytesTxOK);
62
- qemu_put_be64(f, tx_stat->ucastPktsTxOK);
63
- qemu_put_be64(f, tx_stat->ucastBytesTxOK);
64
- qemu_put_be64(f, tx_stat->mcastPktsTxOK);
65
- qemu_put_be64(f, tx_stat->mcastBytesTxOK);
66
- qemu_put_be64(f, tx_stat->bcastPktsTxOK);
67
- qemu_put_be64(f, tx_stat->bcastBytesTxOK);
68
- qemu_put_be64(f, tx_stat->pktsTxError);
69
- qemu_put_be64(f, tx_stat->pktsTxDiscard);
70
-}
71
-
72
-static int vmxnet3_get_txq_descr(QEMUFile *f, void *pv, size_t size,
73
- VMStateField *field)
74
-{
75
- Vmxnet3TxqDescr *r = pv;
76
-
77
- vmxnet3_get_ring_from_file(f, &r->tx_ring);
78
- vmxnet3_get_ring_from_file(f, &r->comp_ring);
79
- r->intr_idx = qemu_get_byte(f);
80
- r->tx_stats_pa = qemu_get_be64(f);
81
-
82
- vmxnet3_get_tx_stats_from_file(f, &r->txq_stats);
83
-
84
- return 0;
229
- return 0;
85
-}
230
-}
86
-
231
-
87
-static int vmxnet3_put_txq_descr(QEMUFile *f, void *pv, size_t size,
232
-
88
- VMStateField *field, QJSON *vmdesc)
233
static int socket_error(void)
89
-{
234
{
90
- Vmxnet3TxqDescr *r = pv;
235
switch (WSAGetLastError()) {
91
-
236
@@ -XXX,XX +XXX,XX @@ static int socket_error(void)
92
- vmxnet3_put_ring_to_file(f, &r->tx_ring);
237
}
93
- vmxnet3_put_ring_to_file(f, &r->comp_ring);
238
}
94
- qemu_put_byte(f, r->intr_idx);
239
95
- qemu_put_be64(f, r->tx_stats_pa);
240
+void qemu_set_block(int fd)
96
- vmxnet3_put_tx_stats_to_file(f, &r->txq_stats);
241
+{
97
-
242
+ unsigned long opt = 0;
98
- return 0;
243
+ WSAEventSelect(fd, NULL, 0);
99
-}
244
+ ioctlsocket(fd, FIONBIO, &opt);
100
-
245
+}
101
-static const VMStateInfo txq_descr_info = {
246
+
102
- .name = "txq_descr",
247
+int qemu_try_set_nonblock(int fd)
103
- .get = vmxnet3_get_txq_descr,
248
+{
104
- .put = vmxnet3_put_txq_descr
249
+ unsigned long opt = 1;
105
+static const VMStateDescription vmstate_vmxnet3_ring = {
250
+ if (ioctlsocket(fd, FIONBIO, &opt) != NO_ERROR) {
106
+ .name = "vmxnet3-ring",
251
+ return -socket_error();
107
+ .version_id = 0,
108
+ .fields = (VMStateField[]) {
109
+ VMSTATE_UINT64(pa, Vmxnet3Ring),
110
+ VMSTATE_UINT32(size, Vmxnet3Ring),
111
+ VMSTATE_UINT32(cell_size, Vmxnet3Ring),
112
+ VMSTATE_UINT32(next, Vmxnet3Ring),
113
+ VMSTATE_UINT8(gen, Vmxnet3Ring),
114
+ VMSTATE_END_OF_LIST()
115
+ }
252
+ }
116
};
253
+ qemu_fd_register(fd);
117
254
+ return 0;
118
-static void vmxnet3_get_rx_stats_from_file(QEMUFile *f,
255
+}
119
- struct UPT1_RxStats *rx_stat)
256
+
120
-{
257
+void qemu_set_nonblock(int fd)
121
- rx_stat->LROPktsRxOK = qemu_get_be64(f);
258
+{
122
- rx_stat->LROBytesRxOK = qemu_get_be64(f);
259
+ (void)qemu_try_set_nonblock(fd);
123
- rx_stat->ucastPktsRxOK = qemu_get_be64(f);
260
+}
124
- rx_stat->ucastBytesRxOK = qemu_get_be64(f);
261
+
125
- rx_stat->mcastPktsRxOK = qemu_get_be64(f);
262
+int socket_set_fast_reuse(int fd)
126
- rx_stat->mcastBytesRxOK = qemu_get_be64(f);
263
+{
127
- rx_stat->bcastPktsRxOK = qemu_get_be64(f);
264
+ /* Enabling the reuse of an endpoint that was used by a socket still in
128
- rx_stat->bcastBytesRxOK = qemu_get_be64(f);
265
+ * TIME_WAIT state is usually performed by setting SO_REUSEADDR. On Windows
129
- rx_stat->pktsRxOutOfBuf = qemu_get_be64(f);
266
+ * fast reuse is the default and SO_REUSEADDR does strange things. So we
130
- rx_stat->pktsRxError = qemu_get_be64(f);
267
+ * don't have to do anything here. More info can be found at:
131
-}
268
+ * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621.aspx */
132
-
269
+ return 0;
133
-static void vmxnet3_put_rx_stats_to_file(QEMUFile *f,
270
+}
134
- struct UPT1_RxStats *rx_stat)
271
+
135
-{
272
int inet_aton(const char *cp, struct in_addr *ia)
136
- qemu_put_be64(f, rx_stat->LROPktsRxOK);
137
- qemu_put_be64(f, rx_stat->LROBytesRxOK);
138
- qemu_put_be64(f, rx_stat->ucastPktsRxOK);
139
- qemu_put_be64(f, rx_stat->ucastBytesRxOK);
140
- qemu_put_be64(f, rx_stat->mcastPktsRxOK);
141
- qemu_put_be64(f, rx_stat->mcastBytesRxOK);
142
- qemu_put_be64(f, rx_stat->bcastPktsRxOK);
143
- qemu_put_be64(f, rx_stat->bcastBytesRxOK);
144
- qemu_put_be64(f, rx_stat->pktsRxOutOfBuf);
145
- qemu_put_be64(f, rx_stat->pktsRxError);
146
-}
147
-
148
-static int vmxnet3_get_rxq_descr(QEMUFile *f, void *pv, size_t size,
149
- VMStateField *field)
150
-{
151
- Vmxnet3RxqDescr *r = pv;
152
- int i;
153
-
154
- for (i = 0; i < VMXNET3_RX_RINGS_PER_QUEUE; i++) {
155
- vmxnet3_get_ring_from_file(f, &r->rx_ring[i]);
156
+static const VMStateDescription vmstate_vmxnet3_tx_stats = {
157
+ .name = "vmxnet3-tx-stats",
158
+ .version_id = 0,
159
+ .fields = (VMStateField[]) {
160
+ VMSTATE_UINT64(TSOPktsTxOK, struct UPT1_TxStats),
161
+ VMSTATE_UINT64(TSOBytesTxOK, struct UPT1_TxStats),
162
+ VMSTATE_UINT64(ucastPktsTxOK, struct UPT1_TxStats),
163
+ VMSTATE_UINT64(ucastBytesTxOK, struct UPT1_TxStats),
164
+ VMSTATE_UINT64(mcastPktsTxOK, struct UPT1_TxStats),
165
+ VMSTATE_UINT64(mcastBytesTxOK, struct UPT1_TxStats),
166
+ VMSTATE_UINT64(bcastPktsTxOK, struct UPT1_TxStats),
167
+ VMSTATE_UINT64(bcastBytesTxOK, struct UPT1_TxStats),
168
+ VMSTATE_UINT64(pktsTxError, struct UPT1_TxStats),
169
+ VMSTATE_UINT64(pktsTxDiscard, struct UPT1_TxStats),
170
+ VMSTATE_END_OF_LIST()
171
}
172
+};
173
174
- vmxnet3_get_ring_from_file(f, &r->comp_ring);
175
- r->intr_idx = qemu_get_byte(f);
176
- r->rx_stats_pa = qemu_get_be64(f);
177
-
178
- vmxnet3_get_rx_stats_from_file(f, &r->rxq_stats);
179
-
180
- return 0;
181
-}
182
-
183
-static int vmxnet3_put_rxq_descr(QEMUFile *f, void *pv, size_t size,
184
- VMStateField *field, QJSON *vmdesc)
185
-{
186
- Vmxnet3RxqDescr *r = pv;
187
- int i;
188
-
189
- for (i = 0; i < VMXNET3_RX_RINGS_PER_QUEUE; i++) {
190
- vmxnet3_put_ring_to_file(f, &r->rx_ring[i]);
191
+static const VMStateDescription vmstate_vmxnet3_txq_descr = {
192
+ .name = "vmxnet3-txq-descr",
193
+ .version_id = 0,
194
+ .fields = (VMStateField[]) {
195
+ VMSTATE_STRUCT(tx_ring, Vmxnet3TxqDescr, 0, vmstate_vmxnet3_ring,
196
+ Vmxnet3Ring),
197
+ VMSTATE_STRUCT(comp_ring, Vmxnet3TxqDescr, 0, vmstate_vmxnet3_ring,
198
+ Vmxnet3Ring),
199
+ VMSTATE_UINT8(intr_idx, Vmxnet3TxqDescr),
200
+ VMSTATE_UINT64(tx_stats_pa, Vmxnet3TxqDescr),
201
+ VMSTATE_STRUCT(txq_stats, Vmxnet3TxqDescr, 0, vmstate_vmxnet3_tx_stats,
202
+ struct UPT1_TxStats),
203
+ VMSTATE_END_OF_LIST()
204
}
205
+};
206
207
- vmxnet3_put_ring_to_file(f, &r->comp_ring);
208
- qemu_put_byte(f, r->intr_idx);
209
- qemu_put_be64(f, r->rx_stats_pa);
210
- vmxnet3_put_rx_stats_to_file(f, &r->rxq_stats);
211
+static const VMStateDescription vmstate_vmxnet3_rx_stats = {
212
+ .name = "vmxnet3-rx-stats",
213
+ .version_id = 0,
214
+ .fields = (VMStateField[]) {
215
+ VMSTATE_UINT64(LROPktsRxOK, struct UPT1_RxStats),
216
+ VMSTATE_UINT64(LROBytesRxOK, struct UPT1_RxStats),
217
+ VMSTATE_UINT64(ucastPktsRxOK, struct UPT1_RxStats),
218
+ VMSTATE_UINT64(ucastBytesRxOK, struct UPT1_RxStats),
219
+ VMSTATE_UINT64(mcastPktsRxOK, struct UPT1_RxStats),
220
+ VMSTATE_UINT64(mcastBytesRxOK, struct UPT1_RxStats),
221
+ VMSTATE_UINT64(bcastPktsRxOK, struct UPT1_RxStats),
222
+ VMSTATE_UINT64(bcastBytesRxOK, struct UPT1_RxStats),
223
+ VMSTATE_UINT64(pktsRxOutOfBuf, struct UPT1_RxStats),
224
+ VMSTATE_UINT64(pktsRxError, struct UPT1_RxStats),
225
+ VMSTATE_END_OF_LIST()
226
+ }
227
+};
228
229
- return 0;
230
-}
231
+static const VMStateDescription vmstate_vmxnet3_rxq_descr = {
232
+ .name = "vmxnet3-rxq-descr",
233
+ .version_id = 0,
234
+ .fields = (VMStateField[]) {
235
+ VMSTATE_STRUCT_ARRAY(rx_ring, Vmxnet3RxqDescr,
236
+ VMXNET3_RX_RINGS_PER_QUEUE, 0,
237
+ vmstate_vmxnet3_ring, Vmxnet3Ring),
238
+ VMSTATE_STRUCT(comp_ring, Vmxnet3RxqDescr, 0, vmstate_vmxnet3_ring,
239
+ Vmxnet3Ring),
240
+ VMSTATE_UINT8(intr_idx, Vmxnet3RxqDescr),
241
+ VMSTATE_UINT64(rx_stats_pa, Vmxnet3RxqDescr),
242
+ VMSTATE_STRUCT(rxq_stats, Vmxnet3RxqDescr, 0, vmstate_vmxnet3_rx_stats,
243
+ struct UPT1_RxStats),
244
+ VMSTATE_END_OF_LIST()
245
+ }
246
+};
247
248
static int vmxnet3_post_load(void *opaque, int version_id)
249
{
273
{
250
@@ -XXX,XX +XXX,XX @@ static int vmxnet3_post_load(void *opaque, int version_id)
274
uint32_t addr = inet_addr(cp);
251
return 0;
252
}
253
254
-static const VMStateInfo rxq_descr_info = {
255
- .name = "rxq_descr",
256
- .get = vmxnet3_get_rxq_descr,
257
- .put = vmxnet3_put_rxq_descr
258
-};
259
-
260
-static int vmxnet3_get_int_state(QEMUFile *f, void *pv, size_t size,
261
- VMStateField *field)
262
-{
263
- Vmxnet3IntState *r = pv;
264
-
265
- r->is_masked = qemu_get_byte(f);
266
- r->is_pending = qemu_get_byte(f);
267
- r->is_asserted = qemu_get_byte(f);
268
-
269
- return 0;
270
-}
271
-
272
-static int vmxnet3_put_int_state(QEMUFile *f, void *pv, size_t size,
273
- VMStateField *field, QJSON *vmdesc)
274
-{
275
- Vmxnet3IntState *r = pv;
276
-
277
- qemu_put_byte(f, r->is_masked);
278
- qemu_put_byte(f, r->is_pending);
279
- qemu_put_byte(f, r->is_asserted);
280
-
281
- return 0;
282
-}
283
-
284
-static const VMStateInfo int_state_info = {
285
- .name = "int_state",
286
- .get = vmxnet3_get_int_state,
287
- .put = vmxnet3_put_int_state
288
+static const VMStateDescription vmstate_vmxnet3_int_state = {
289
+ .name = "vmxnet3-int-state",
290
+ .version_id = 0,
291
+ .fields = (VMStateField[]) {
292
+ VMSTATE_BOOL(is_masked, Vmxnet3IntState),
293
+ VMSTATE_BOOL(is_pending, Vmxnet3IntState),
294
+ VMSTATE_BOOL(is_asserted, Vmxnet3IntState),
295
+ VMSTATE_END_OF_LIST()
296
+ }
297
};
298
299
static bool vmxnet3_vmstate_need_pcie_device(void *opaque)
300
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_vmxnet3 = {
301
VMSTATE_UINT64(drv_shmem, VMXNET3State),
302
VMSTATE_UINT64(temp_shared_guest_driver_memory, VMXNET3State),
303
304
- VMSTATE_ARRAY(txq_descr, VMXNET3State,
305
- VMXNET3_DEVICE_MAX_TX_QUEUES, 0, txq_descr_info,
306
+ VMSTATE_STRUCT_ARRAY(txq_descr, VMXNET3State,
307
+ VMXNET3_DEVICE_MAX_TX_QUEUES, 0, vmstate_vmxnet3_txq_descr,
308
Vmxnet3TxqDescr),
309
- VMSTATE_ARRAY(rxq_descr, VMXNET3State,
310
- VMXNET3_DEVICE_MAX_RX_QUEUES, 0, rxq_descr_info,
311
+ VMSTATE_STRUCT_ARRAY(rxq_descr, VMXNET3State,
312
+ VMXNET3_DEVICE_MAX_RX_QUEUES, 0, vmstate_vmxnet3_rxq_descr,
313
Vmxnet3RxqDescr),
314
- VMSTATE_ARRAY(interrupt_states, VMXNET3State, VMXNET3_MAX_INTRS,
315
- 0, int_state_info, Vmxnet3IntState),
316
+ VMSTATE_STRUCT_ARRAY(interrupt_states, VMXNET3State,
317
+ VMXNET3_MAX_INTRS, 0, vmstate_vmxnet3_int_state,
318
+ Vmxnet3IntState),
319
320
VMSTATE_END_OF_LIST()
321
},
322
--
275
--
323
2.7.4
276
2.5.0
324
277
325
278
diff view generated by jsdifflib
1
From: Dmitry Fleytman <dmitry@daynix.com>
1
From: "Daniel P. Berrange" <berrange@redhat.com>
2
2
3
Make VLAN stripping functions return number of bytes
3
When QEMU sets up a tap based network device backend, it mostly ignores errors
4
copied to given Ethernet header buffer.
4
reported from various ioctl() calls it makes, assuming the TAP file descriptor
5
is valid. This assumption can easily be violated when the user is passing in a
6
pre-opened file descriptor. At best, the ioctls may fail with a -EBADF, but if
7
the user passes in a bogus FD number that happens to clash with a FD number that
8
QEMU has opened internally for another reason, a wide variety of errnos may
9
result, as the TUNGETIFF ioctl number may map to a completely different command
10
on a different type of file.
5
11
6
This information should be used to re-compose
12
By ignoring all these errors, QEMU sets up a zombie network backend that will
7
packet IOV after VLAN stripping.
13
never pass any data. Even worse, when QEMU shuts down, or that network backend
14
is hot-removed, it will close this bogus file descriptor, which could belong to
15
another QEMU device backend.
8
16
9
Cc: qemu-stable@nongnu.org
17
There's no obvious guaranteed reliable way to detect that a FD genuinely is a
10
Signed-off-by: Dmitry Fleytman <dmitry@daynix.com>
18
TAP device, as opposed to a UNIX socket, or pipe, or something else. Checking
19
the errno from probing vnet hdr flag though, does catch the big common cases.
20
ie calling TUNGETIFF will return EBADF for an invalid FD, and ENOTTY when FD is
21
a UNIX socket, or pipe which catches accidental collisions with FDs used for
22
stdio, or monitor socket.
23
24
Previously the example below where bogus fd 9 collides with the FD used for the
25
chardev saw:
26
27
$ ./x86_64-softmmu/qemu-system-x86_64 -netdev tap,id=hostnet0,fd=9 \
28
-chardev socket,id=charchannel0,path=/tmp/qga,server,nowait \
29
-monitor stdio -vnc :0
30
qemu-system-x86_64: -netdev tap,id=hostnet0,fd=9: TUNGETIFF ioctl() failed: Inappropriate ioctl for device
31
TUNSETOFFLOAD ioctl() failed: Bad address
32
QEMU 2.9.1 monitor - type 'help' for more information
33
(qemu) Warning: netdev hostnet0 has no peer
34
35
which gives a running QEMU with a zombie network backend.
36
37
With this change applied we get an error message and QEMU immediately exits
38
before carrying on and making a bigger disaster:
39
40
$ ./x86_64-softmmu/qemu-system-x86_64 -netdev tap,id=hostnet0,fd=9 \
41
-chardev socket,id=charchannel0,path=/tmp/qga,server,nowait \
42
-monitor stdio -vnc :0
43
qemu-system-x86_64: -netdev tap,id=hostnet0,vhost=on,fd=9: Unable to query TUNGETIFF on FD 9: Inappropriate ioctl for device
44
45
Reported-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
46
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
47
Tested-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
48
Message-id: 20171027085548.3472-1-berrange@redhat.com
49
[lv: to simplify, don't check on EINVAL with TUNGETIFF as it exists since v2.6.27]
50
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
51
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
52
---
13
include/net/eth.h | 4 ++--
53
net/tap-bsd.c | 2 +-
14
net/eth.c | 25 ++++++++++++++-----------
54
net/tap-linux.c | 8 +++++---
15
2 files changed, 16 insertions(+), 13 deletions(-)
55
net/tap-solaris.c | 2 +-
56
net/tap-stub.c | 2 +-
57
net/tap.c | 25 ++++++++++++++++++++-----
58
net/tap_int.h | 2 +-
59
6 files changed, 29 insertions(+), 12 deletions(-)
16
60
17
diff --git a/include/net/eth.h b/include/net/eth.h
61
diff --git a/net/tap-bsd.c b/net/tap-bsd.c
18
index XXXXXXX..XXXXXXX 100644
62
index XXXXXXX..XXXXXXX 100644
19
--- a/include/net/eth.h
63
--- a/net/tap-bsd.c
20
+++ b/include/net/eth.h
64
+++ b/net/tap-bsd.c
21
@@ -XXX,XX +XXX,XX @@ eth_get_pkt_tci(const void *p)
65
@@ -XXX,XX +XXX,XX @@ void tap_set_sndbuf(int fd, const NetdevTapOptions *tap, Error **errp)
66
{
67
}
68
69
-int tap_probe_vnet_hdr(int fd)
70
+int tap_probe_vnet_hdr(int fd, Error **errp)
71
{
72
return 0;
73
}
74
diff --git a/net/tap-linux.c b/net/tap-linux.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/net/tap-linux.c
77
+++ b/net/tap-linux.c
78
@@ -XXX,XX +XXX,XX @@ void tap_set_sndbuf(int fd, const NetdevTapOptions *tap, Error **errp)
22
}
79
}
23
}
80
}
24
81
25
-bool
82
-int tap_probe_vnet_hdr(int fd)
26
+size_t
83
+int tap_probe_vnet_hdr(int fd, Error **errp)
27
eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff,
84
{
28
uint8_t *new_ehdr_buf,
85
struct ifreq ifr;
29
uint16_t *payload_offset, uint16_t *tci);
86
30
87
if (ioctl(fd, TUNGETIFF, &ifr) != 0) {
31
-bool
88
- error_report("TUNGETIFF ioctl() failed: %s", strerror(errno));
32
+size_t
89
- return 0;
33
eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff,
90
+ /* TUNGETIFF is available since kernel v2.6.27 */
34
uint16_t vet, uint8_t *new_ehdr_buf,
91
+ error_setg_errno(errp, errno,
35
uint16_t *payload_offset, uint16_t *tci);
92
+ "Unable to query TUNGETIFF on FD %d", fd);
36
diff --git a/net/eth.c b/net/eth.c
93
+ return -1;
94
}
95
96
return ifr.ifr_flags & IFF_VNET_HDR;
97
diff --git a/net/tap-solaris.c b/net/tap-solaris.c
37
index XXXXXXX..XXXXXXX 100644
98
index XXXXXXX..XXXXXXX 100644
38
--- a/net/eth.c
99
--- a/net/tap-solaris.c
39
+++ b/net/eth.c
100
+++ b/net/tap-solaris.c
40
@@ -XXX,XX +XXX,XX @@ void eth_get_protocols(const struct iovec *iov, int iovcnt,
101
@@ -XXX,XX +XXX,XX @@ void tap_set_sndbuf(int fd, const NetdevTapOptions *tap, Error **errp)
102
{
103
}
104
105
-int tap_probe_vnet_hdr(int fd)
106
+int tap_probe_vnet_hdr(int fd, Error **errp)
107
{
108
return 0;
109
}
110
diff --git a/net/tap-stub.c b/net/tap-stub.c
111
index XXXXXXX..XXXXXXX 100644
112
--- a/net/tap-stub.c
113
+++ b/net/tap-stub.c
114
@@ -XXX,XX +XXX,XX @@ void tap_set_sndbuf(int fd, const NetdevTapOptions *tap, Error **errp)
115
{
116
}
117
118
-int tap_probe_vnet_hdr(int fd)
119
+int tap_probe_vnet_hdr(int fd, Error **errp)
120
{
121
return 0;
122
}
123
diff --git a/net/tap.c b/net/tap.c
124
index XXXXXXX..XXXXXXX 100644
125
--- a/net/tap.c
126
+++ b/net/tap.c
127
@@ -XXX,XX +XXX,XX @@ int net_init_bridge(const Netdev *netdev, const char *name,
41
}
128
}
42
}
129
43
130
qemu_set_nonblock(fd);
44
-bool
131
- vnet_hdr = tap_probe_vnet_hdr(fd);
45
+size_t
132
+ vnet_hdr = tap_probe_vnet_hdr(fd, errp);
46
eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff,
133
+ if (vnet_hdr < 0) {
47
uint8_t *new_ehdr_buf,
134
+ close(fd);
48
uint16_t *payload_offset, uint16_t *tci)
135
+ return -1;
49
@@ -XXX,XX +XXX,XX @@ eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff,
136
+ }
50
new_ehdr, sizeof(*new_ehdr));
137
s = net_tap_fd_init(peer, "bridge", name, fd, vnet_hdr);
51
138
52
if (copied < sizeof(*new_ehdr)) {
139
snprintf(s->nc.info_str, sizeof(s->nc.info_str), "helper=%s,br=%s", helper,
53
- return false;
140
@@ -XXX,XX +XXX,XX @@ int net_init_tap(const Netdev *netdev, const char *name,
54
+ return 0;
141
return -1;
55
}
56
57
switch (be16_to_cpu(new_ehdr->h_proto)) {
58
@@ -XXX,XX +XXX,XX @@ eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff,
59
&vlan_hdr, sizeof(vlan_hdr));
60
61
if (copied < sizeof(vlan_hdr)) {
62
- return false;
63
+ return 0;
64
}
142
}
65
143
66
new_ehdr->h_proto = vlan_hdr.h_proto;
144
- vnet_hdr = tap_probe_vnet_hdr(fd);
67
@@ -XXX,XX +XXX,XX @@ eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff,
145
+ vnet_hdr = tap_probe_vnet_hdr(fd, errp);
68
PKT_GET_VLAN_HDR(new_ehdr), sizeof(vlan_hdr));
146
+ if (vnet_hdr < 0) {
69
147
+ close(fd);
70
if (copied < sizeof(vlan_hdr)) {
148
+ return -1;
71
- return false;
149
+ }
72
+ return 0;
150
151
net_init_tap_one(tap, peer, "tap", name, NULL,
152
script, downscript,
153
@@ -XXX,XX +XXX,XX @@ int net_init_tap(const Netdev *netdev, const char *name,
73
}
154
}
74
155
75
*payload_offset += sizeof(vlan_hdr);
156
if (i == 0) {
76
+
157
- vnet_hdr = tap_probe_vnet_hdr(fd);
77
+ return sizeof(struct eth_header) + sizeof(struct vlan_header);
158
- } else if (vnet_hdr != tap_probe_vnet_hdr(fd)) {
78
+ } else {
159
+ vnet_hdr = tap_probe_vnet_hdr(fd, errp);
79
+ return sizeof(struct eth_header);
160
+ if (vnet_hdr < 0) {
161
+ goto free_fail;
162
+ }
163
+ } else if (vnet_hdr != tap_probe_vnet_hdr(fd, NULL)) {
164
error_setg(errp,
165
"vnet_hdr not consistent across given tap fds");
166
ret = -1;
167
@@ -XXX,XX +XXX,XX @@ free_fail:
80
}
168
}
81
- return true;
169
82
default:
170
qemu_set_nonblock(fd);
83
- return false;
171
- vnet_hdr = tap_probe_vnet_hdr(fd);
84
+ return 0;
172
+ vnet_hdr = tap_probe_vnet_hdr(fd, errp);
85
}
173
+ if (vnet_hdr < 0) {
86
}
174
+ close(fd);
87
175
+ return -1;
88
-bool
176
+ }
89
+size_t
177
90
eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff,
178
net_init_tap_one(tap, peer, "bridge", name, ifname,
91
uint16_t vet, uint8_t *new_ehdr_buf,
179
script, downscript, vhostfdname,
92
uint16_t *payload_offset, uint16_t *tci)
180
diff --git a/net/tap_int.h b/net/tap_int.h
93
@@ -XXX,XX +XXX,XX @@ eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff,
181
index XXXXXXX..XXXXXXX 100644
94
new_ehdr, sizeof(*new_ehdr));
182
--- a/net/tap_int.h
95
183
+++ b/net/tap_int.h
96
if (copied < sizeof(*new_ehdr)) {
184
@@ -XXX,XX +XXX,XX @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
97
- return false;
185
ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen);
98
+ return 0;
186
99
}
187
void tap_set_sndbuf(int fd, const NetdevTapOptions *tap, Error **errp);
100
188
-int tap_probe_vnet_hdr(int fd);
101
if (be16_to_cpu(new_ehdr->h_proto) == vet) {
189
+int tap_probe_vnet_hdr(int fd, Error **errp);
102
@@ -XXX,XX +XXX,XX @@ eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff,
190
int tap_probe_vnet_hdr_len(int fd, int len);
103
&vlan_hdr, sizeof(vlan_hdr));
191
int tap_probe_has_ufo(int fd);
104
192
void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo);
105
if (copied < sizeof(vlan_hdr)) {
106
- return false;
107
+ return 0;
108
}
109
110
new_ehdr->h_proto = vlan_hdr.h_proto;
111
112
*tci = be16_to_cpu(vlan_hdr.h_tci);
113
*payload_offset = iovoff + sizeof(*new_ehdr) + sizeof(vlan_hdr);
114
- return true;
115
+ return sizeof(struct eth_header);
116
}
117
118
- return false;
119
+ return 0;
120
}
121
122
void
123
--
193
--
124
2.7.4
194
2.5.0
125
195
126
196
diff view generated by jsdifflib
Deleted patch
1
From: Dmitry Fleytman <dmitry@daynix.com>
2
1
3
This patch fixed a problem that was introduced in commit eb700029.
4
5
When net_rx_pkt_attach_iovec() calls eth_strip_vlan()
6
this can result in pkt->ehdr_buf being overflowed, because
7
ehdr_buf is only sizeof(struct eth_header) bytes large
8
but eth_strip_vlan() can write
9
sizeof(struct eth_header) + sizeof(struct vlan_header)
10
bytes into it.
11
12
Devices affected by this problem: vmxnet3.
13
14
Cc: qemu-stable@nongnu.org
15
Reported-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Dmitry Fleytman <dmitry@daynix.com>
17
Signed-off-by: Jason Wang <jasowang@redhat.com>
18
---
19
hw/net/net_rx_pkt.c | 34 +++++++++++++++++-----------------
20
1 file changed, 17 insertions(+), 17 deletions(-)
21
22
diff --git a/hw/net/net_rx_pkt.c b/hw/net/net_rx_pkt.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/net/net_rx_pkt.c
25
+++ b/hw/net/net_rx_pkt.c
26
@@ -XXX,XX +XXX,XX @@
27
28
struct NetRxPkt {
29
struct virtio_net_hdr virt_hdr;
30
- uint8_t ehdr_buf[sizeof(struct eth_header)];
31
+ uint8_t ehdr_buf[sizeof(struct eth_header) + sizeof(struct vlan_header)];
32
struct iovec *vec;
33
uint16_t vec_len_total;
34
uint16_t vec_len;
35
uint32_t tot_len;
36
uint16_t tci;
37
- bool vlan_stripped;
38
+ size_t ehdr_buf_len;
39
bool has_virt_hdr;
40
eth_pkt_types_e packet_type;
41
42
@@ -XXX,XX +XXX,XX @@ net_rx_pkt_pull_data(struct NetRxPkt *pkt,
43
const struct iovec *iov, int iovcnt,
44
size_t ploff)
45
{
46
- if (pkt->vlan_stripped) {
47
+ if (pkt->ehdr_buf_len) {
48
net_rx_pkt_iovec_realloc(pkt, iovcnt + 1);
49
50
pkt->vec[0].iov_base = pkt->ehdr_buf;
51
- pkt->vec[0].iov_len = sizeof(pkt->ehdr_buf);
52
-
53
- pkt->tot_len =
54
- iov_size(iov, iovcnt) - ploff + sizeof(struct eth_header);
55
+ pkt->vec[0].iov_len = pkt->ehdr_buf_len;
56
57
+ pkt->tot_len = iov_size(iov, iovcnt) - ploff + pkt->ehdr_buf_len;
58
pkt->vec_len = iov_copy(pkt->vec + 1, pkt->vec_len_total - 1,
59
iov, iovcnt, ploff, pkt->tot_len);
60
} else {
61
@@ -XXX,XX +XXX,XX @@ void net_rx_pkt_attach_iovec(struct NetRxPkt *pkt,
62
uint16_t tci = 0;
63
uint16_t ploff = iovoff;
64
assert(pkt);
65
- pkt->vlan_stripped = false;
66
67
if (strip_vlan) {
68
- pkt->vlan_stripped = eth_strip_vlan(iov, iovcnt, iovoff, pkt->ehdr_buf,
69
- &ploff, &tci);
70
+ pkt->ehdr_buf_len = eth_strip_vlan(iov, iovcnt, iovoff, pkt->ehdr_buf,
71
+ &ploff, &tci);
72
+ } else {
73
+ pkt->ehdr_buf_len = 0;
74
}
75
76
pkt->tci = tci;
77
@@ -XXX,XX +XXX,XX @@ void net_rx_pkt_attach_iovec_ex(struct NetRxPkt *pkt,
78
uint16_t tci = 0;
79
uint16_t ploff = iovoff;
80
assert(pkt);
81
- pkt->vlan_stripped = false;
82
83
if (strip_vlan) {
84
- pkt->vlan_stripped = eth_strip_vlan_ex(iov, iovcnt, iovoff, vet,
85
- pkt->ehdr_buf,
86
- &ploff, &tci);
87
+ pkt->ehdr_buf_len = eth_strip_vlan_ex(iov, iovcnt, iovoff, vet,
88
+ pkt->ehdr_buf,
89
+ &ploff, &tci);
90
+ } else {
91
+ pkt->ehdr_buf_len = 0;
92
}
93
94
pkt->tci = tci;
95
@@ -XXX,XX +XXX,XX @@ void net_rx_pkt_dump(struct NetRxPkt *pkt)
96
#ifdef NET_RX_PKT_DEBUG
97
assert(pkt);
98
99
- printf("RX PKT: tot_len: %d, vlan_stripped: %d, vlan_tag: %d\n",
100
- pkt->tot_len, pkt->vlan_stripped, pkt->tci);
101
+ printf("RX PKT: tot_len: %d, ehdr_buf_len: %lu, vlan_tag: %d\n",
102
+ pkt->tot_len, pkt->ehdr_buf_len, pkt->tci);
103
#endif
104
}
105
106
@@ -XXX,XX +XXX,XX @@ bool net_rx_pkt_is_vlan_stripped(struct NetRxPkt *pkt)
107
{
108
assert(pkt);
109
110
- return pkt->vlan_stripped;
111
+ return pkt->ehdr_buf_len ? true : false;
112
}
113
114
bool net_rx_pkt_has_virt_hdr(struct NetRxPkt *pkt)
115
--
116
2.7.4
117
118
diff view generated by jsdifflib
Deleted patch
1
From: Dmitry Fleytman <dmitry@daynix.com>
2
1
3
In case of VLAN stripping, ETH header put into a
4
separate buffer, therefore amont of data copied
5
from original IOV should be smaller.
6
7
Cc: qemu-stable@nongnu.org
8
Signed-off-by: Dmitry Fleytman <dmitry@daynix.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
11
hw/net/net_rx_pkt.c | 3 ++-
12
1 file changed, 2 insertions(+), 1 deletion(-)
13
14
diff --git a/hw/net/net_rx_pkt.c b/hw/net/net_rx_pkt.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/net/net_rx_pkt.c
17
+++ b/hw/net/net_rx_pkt.c
18
@@ -XXX,XX +XXX,XX @@ net_rx_pkt_pull_data(struct NetRxPkt *pkt,
19
20
pkt->tot_len = iov_size(iov, iovcnt) - ploff + pkt->ehdr_buf_len;
21
pkt->vec_len = iov_copy(pkt->vec + 1, pkt->vec_len_total - 1,
22
- iov, iovcnt, ploff, pkt->tot_len);
23
+ iov, iovcnt, ploff,
24
+ pkt->tot_len - pkt->ehdr_buf_len);
25
} else {
26
net_rx_pkt_iovec_realloc(pkt, iovcnt);
27
28
--
29
2.7.4
30
31
diff view generated by jsdifflib
Deleted patch
1
From: Dmitry Fleytman <dmitry@daynix.com>
2
1
3
In case of VLAN stripping ETH header is stored in a
4
separate chunk and length of IOV should take this into
5
account.
6
7
This patch fixes checksum validation for RX packets
8
with VLAN header.
9
10
Devices affected by this problem: e1000e and vmxnet3.
11
12
Cc: qemu-stable@nongnu.org
13
Signed-off-by: Dmitry Fleytman <dmitry@daynix.com>
14
Signed-off-by: Jason Wang <jasowang@redhat.com>
15
---
16
hw/net/net_rx_pkt.c | 2 +-
17
1 file changed, 1 insertion(+), 1 deletion(-)
18
19
diff --git a/hw/net/net_rx_pkt.c b/hw/net/net_rx_pkt.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/net/net_rx_pkt.c
22
+++ b/hw/net/net_rx_pkt.c
23
@@ -XXX,XX +XXX,XX @@ net_rx_pkt_pull_data(struct NetRxPkt *pkt,
24
pkt->tot_len = iov_size(iov, iovcnt) - ploff + pkt->ehdr_buf_len;
25
pkt->vec_len = iov_copy(pkt->vec + 1, pkt->vec_len_total - 1,
26
iov, iovcnt, ploff,
27
- pkt->tot_len - pkt->ehdr_buf_len);
28
+ pkt->tot_len - pkt->ehdr_buf_len) + 1;
29
} else {
30
net_rx_pkt_iovec_realloc(pkt, iovcnt);
31
32
--
33
2.7.4
34
35
diff view generated by jsdifflib
Deleted patch
1
From: Dmitry Fleytman <dmitry@daynix.com>
2
1
3
This is a refactoring commit that does not change behavior.
4
5
Signed-off-by: Dmitry Fleytman <dmitry@daynix.com>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
---
8
hw/net/net_rx_pkt.c | 9 +++++----
9
1 file changed, 5 insertions(+), 4 deletions(-)
10
11
diff --git a/hw/net/net_rx_pkt.c b/hw/net/net_rx_pkt.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/net/net_rx_pkt.c
14
+++ b/hw/net/net_rx_pkt.c
15
@@ -XXX,XX +XXX,XX @@ net_rx_pkt_pull_data(struct NetRxPkt *pkt,
16
const struct iovec *iov, int iovcnt,
17
size_t ploff)
18
{
19
+ uint32_t pllen = iov_size(iov, iovcnt) - ploff;
20
+
21
if (pkt->ehdr_buf_len) {
22
net_rx_pkt_iovec_realloc(pkt, iovcnt + 1);
23
24
pkt->vec[0].iov_base = pkt->ehdr_buf;
25
pkt->vec[0].iov_len = pkt->ehdr_buf_len;
26
27
- pkt->tot_len = iov_size(iov, iovcnt) - ploff + pkt->ehdr_buf_len;
28
+ pkt->tot_len = pllen + pkt->ehdr_buf_len;
29
pkt->vec_len = iov_copy(pkt->vec + 1, pkt->vec_len_total - 1,
30
- iov, iovcnt, ploff,
31
- pkt->tot_len - pkt->ehdr_buf_len) + 1;
32
+ iov, iovcnt, ploff, pllen) + 1;
33
} else {
34
net_rx_pkt_iovec_realloc(pkt, iovcnt);
35
36
- pkt->tot_len = iov_size(iov, iovcnt) - ploff;
37
+ pkt->tot_len = pllen;
38
pkt->vec_len = iov_copy(pkt->vec, pkt->vec_len_total,
39
iov, iovcnt, ploff, pkt->tot_len);
40
}
41
--
42
2.7.4
43
44
diff view generated by jsdifflib
1
From: zhanghailiang <zhang.zhanghailiang@huawei.com>
1
From: erik-smit <erik.lucas.smit@gmail.com>
2
2
3
Instead of using qemu timer to process the stale packets,
3
The test of the write of the dblac register was testing the old value
4
We re-use the colo compare thread to process these packets
4
instead of the new value. This would accept the write of an invalid value
5
by creating a new timeout coroutine.
5
but subsequently refuse any following valid writes.
6
6
7
Besides, since we process all the same vNIC's net connection/packets
7
Signed-off-by: erik-smit <erik.lucas.smit@gmail.com>
8
in one thread, it is safe to remove the timer_check_lock.
8
Reviewed-by: Cédric Le Goater <clg@kaod.org>
9
10
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
10
---
13
net/colo-compare.c | 62 +++++++++++++++++++-----------------------------------
11
hw/net/ftgmac100.c | 14 ++++++++------
14
1 file changed, 22 insertions(+), 40 deletions(-)
12
1 file changed, 8 insertions(+), 6 deletions(-)
15
13
16
diff --git a/net/colo-compare.c b/net/colo-compare.c
14
diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c
17
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
18
--- a/net/colo-compare.c
16
--- a/hw/net/ftgmac100.c
19
+++ b/net/colo-compare.c
17
+++ b/hw/net/ftgmac100.c
20
@@ -XXX,XX +XXX,XX @@ typedef struct CompareState {
18
@@ -XXX,XX +XXX,XX @@ static void ftgmac100_write(void *opaque, hwaddr addr,
21
GHashTable *connection_track_table;
19
s->phydata = value & 0xffff;
22
/* compare thread, a thread for each NIC */
20
break;
23
QemuThread thread;
21
case FTGMAC100_DBLAC: /* DMA Burst Length and Arbitration Control */
24
- /* Timer used on the primary to find packets that are never matched */
22
- if (FTGMAC100_DBLAC_TXDES_SIZE(s->dblac) < sizeof(FTGMAC100Desc)) {
25
- QEMUTimer *timer;
23
+ if (FTGMAC100_DBLAC_TXDES_SIZE(value) < sizeof(FTGMAC100Desc)) {
26
- QemuMutex timer_check_lock;
24
qemu_log_mask(LOG_GUEST_ERROR,
27
} CompareState;
25
- "%s: transmit descriptor too small : %d bytes\n",
28
26
- __func__, FTGMAC100_DBLAC_TXDES_SIZE(s->dblac));
29
typedef struct CompareClass {
27
+ "%s: transmit descriptor too small: %" PRIx64
30
@@ -XXX,XX +XXX,XX @@ static void colo_compare_connection(void *opaque, void *user_data)
28
+ " bytes\n", __func__,
31
29
+ FTGMAC100_DBLAC_TXDES_SIZE(value));
32
while (!g_queue_is_empty(&conn->primary_list) &&
33
!g_queue_is_empty(&conn->secondary_list)) {
34
- qemu_mutex_lock(&s->timer_check_lock);
35
pkt = g_queue_pop_tail(&conn->primary_list);
36
- qemu_mutex_unlock(&s->timer_check_lock);
37
switch (conn->ip_proto) {
38
case IPPROTO_TCP:
39
result = g_queue_find_custom(&conn->secondary_list,
40
@@ -XXX,XX +XXX,XX @@ static void colo_compare_connection(void *opaque, void *user_data)
41
* until next comparison.
42
*/
43
trace_colo_compare_main("packet different");
44
- qemu_mutex_lock(&s->timer_check_lock);
45
g_queue_push_tail(&conn->primary_list, pkt);
46
- qemu_mutex_unlock(&s->timer_check_lock);
47
/* TODO: colo_notify_checkpoint();*/
48
break;
30
break;
49
}
31
}
50
@@ -XXX,XX +XXX,XX @@ static void compare_sec_chr_in(void *opaque, const uint8_t *buf, int size)
32
- if (FTGMAC100_DBLAC_RXDES_SIZE(s->dblac) < sizeof(FTGMAC100Desc)) {
51
}
33
+ if (FTGMAC100_DBLAC_RXDES_SIZE(value) < sizeof(FTGMAC100Desc)) {
52
}
34
qemu_log_mask(LOG_GUEST_ERROR,
53
35
- "%s: receive descriptor too small : %d bytes\n",
54
+/*
36
- __func__, FTGMAC100_DBLAC_RXDES_SIZE(s->dblac));
55
+ * Check old packet regularly so it can watch for any packets
37
+ "%s: receive descriptor too small : %" PRIx64
56
+ * that the secondary hasn't produced equivalents of.
38
+ " bytes\n", __func__,
57
+ */
39
+ FTGMAC100_DBLAC_RXDES_SIZE(value));
58
+static gboolean check_old_packet_regular(void *opaque)
40
break;
59
+{
41
}
60
+ CompareState *s = opaque;
42
s->dblac = value;
61
+
62
+ /* if have old packet we will notify checkpoint */
63
+ colo_old_packet_check(s);
64
+
65
+ return TRUE;
66
+}
67
+
68
static void *colo_compare_thread(void *opaque)
69
{
70
GMainContext *worker_context;
71
GMainLoop *compare_loop;
72
CompareState *s = opaque;
73
+ GSource *timeout_source;
74
75
worker_context = g_main_context_new();
76
77
@@ -XXX,XX +XXX,XX @@ static void *colo_compare_thread(void *opaque)
78
79
compare_loop = g_main_loop_new(worker_context, FALSE);
80
81
+ /* To kick any packets that the secondary doesn't match */
82
+ timeout_source = g_timeout_source_new(REGULAR_PACKET_CHECK_MS);
83
+ g_source_set_callback(timeout_source,
84
+ (GSourceFunc)check_old_packet_regular, s, NULL);
85
+ g_source_attach(timeout_source, worker_context);
86
+
87
g_main_loop_run(compare_loop);
88
89
+ g_source_unref(timeout_source);
90
g_main_loop_unref(compare_loop);
91
g_main_context_unref(worker_context);
92
return NULL;
93
@@ -XXX,XX +XXX,XX @@ static int find_and_check_chardev(Chardev **chr,
94
}
95
96
/*
97
- * Check old packet regularly so it can watch for any packets
98
- * that the secondary hasn't produced equivalents of.
99
- */
100
-static void check_old_packet_regular(void *opaque)
101
-{
102
- CompareState *s = opaque;
103
-
104
- timer_mod(s->timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
105
- REGULAR_PACKET_CHECK_MS);
106
- /* if have old packet we will notify checkpoint */
107
- /*
108
- * TODO: Make timer handler run in compare thread
109
- * like qemu_chr_add_handlers_full.
110
- */
111
- qemu_mutex_lock(&s->timer_check_lock);
112
- colo_old_packet_check(s);
113
- qemu_mutex_unlock(&s->timer_check_lock);
114
-}
115
-
116
-/*
117
* Called from the main thread on the primary
118
* to setup colo-compare.
119
*/
120
@@ -XXX,XX +XXX,XX @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
121
net_socket_rs_init(&s->sec_rs, compare_sec_rs_finalize);
122
123
g_queue_init(&s->conn_list);
124
- qemu_mutex_init(&s->timer_check_lock);
125
126
s->connection_track_table = g_hash_table_new_full(connection_key_hash,
127
connection_key_equal,
128
@@ -XXX,XX +XXX,XX @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
129
QEMU_THREAD_JOINABLE);
130
compare_id++;
131
132
- /* A regular timer to kick any packets that the secondary doesn't match */
133
- s->timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, /* Only when guest runs */
134
- check_old_packet_regular, s);
135
- timer_mod(s->timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
136
- REGULAR_PACKET_CHECK_MS);
137
-
138
return;
139
}
140
141
@@ -XXX,XX +XXX,XX @@ static void colo_compare_finalize(Object *obj)
142
qemu_thread_join(&s->thread);
143
}
144
145
- if (s->timer) {
146
- timer_del(s->timer);
147
- }
148
-
149
- qemu_mutex_destroy(&s->timer_check_lock);
150
-
151
g_free(s->pri_indev);
152
g_free(s->sec_indev);
153
g_free(s->outdev);
154
--
43
--
155
2.7.4
44
2.5.0
156
45
157
46
diff view generated by jsdifflib
Deleted patch
1
From: zhanghailiang <zhang.zhanghailiang@huawei.com>
2
1
3
We should call g_main_loop_quit() to notify colo compare thread to
4
exit, Or it will run in g_main_loop_run() forever.
5
6
Besides, the finalizing process can't happen in context of colo thread,
7
it is reasonable to remove the 'if (qemu_thread_is_self(&s->thread))'
8
branch.
9
10
Before compare thead exits, some cleanup works need to be
11
done, All unhandled packets need to be released and connection_track_table
12
needs to be freed, or there will be memory leak.
13
14
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
15
Reviewed-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
16
Signed-off-by: Jason Wang <jasowang@redhat.com>
17
---
18
net/colo-compare.c | 39 +++++++++++++++++++++++++++++----------
19
1 file changed, 29 insertions(+), 10 deletions(-)
20
21
diff --git a/net/colo-compare.c b/net/colo-compare.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/net/colo-compare.c
24
+++ b/net/colo-compare.c
25
@@ -XXX,XX +XXX,XX @@ typedef struct CompareState {
26
GHashTable *connection_track_table;
27
/* compare thread, a thread for each NIC */
28
QemuThread thread;
29
+
30
+ GMainLoop *compare_loop;
31
} CompareState;
32
33
typedef struct CompareClass {
34
@@ -XXX,XX +XXX,XX @@ static gboolean check_old_packet_regular(void *opaque)
35
static void *colo_compare_thread(void *opaque)
36
{
37
GMainContext *worker_context;
38
- GMainLoop *compare_loop;
39
CompareState *s = opaque;
40
GSource *timeout_source;
41
42
@@ -XXX,XX +XXX,XX @@ static void *colo_compare_thread(void *opaque)
43
qemu_chr_fe_set_handlers(&s->chr_sec_in, compare_chr_can_read,
44
compare_sec_chr_in, NULL, s, worker_context, true);
45
46
- compare_loop = g_main_loop_new(worker_context, FALSE);
47
+ s->compare_loop = g_main_loop_new(worker_context, FALSE);
48
49
/* To kick any packets that the secondary doesn't match */
50
timeout_source = g_timeout_source_new(REGULAR_PACKET_CHECK_MS);
51
@@ -XXX,XX +XXX,XX @@ static void *colo_compare_thread(void *opaque)
52
(GSourceFunc)check_old_packet_regular, s, NULL);
53
g_source_attach(timeout_source, worker_context);
54
55
- g_main_loop_run(compare_loop);
56
+ g_main_loop_run(s->compare_loop);
57
58
g_source_unref(timeout_source);
59
- g_main_loop_unref(compare_loop);
60
+ g_main_loop_unref(s->compare_loop);
61
g_main_context_unref(worker_context);
62
return NULL;
63
}
64
@@ -XXX,XX +XXX,XX @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
65
return;
66
}
67
68
+static void colo_flush_packets(void *opaque, void *user_data)
69
+{
70
+ CompareState *s = user_data;
71
+ Connection *conn = opaque;
72
+ Packet *pkt = NULL;
73
+
74
+ while (!g_queue_is_empty(&conn->primary_list)) {
75
+ pkt = g_queue_pop_head(&conn->primary_list);
76
+ compare_chr_send(&s->chr_out, pkt->data, pkt->size);
77
+ packet_destroy(pkt, NULL);
78
+ }
79
+ while (!g_queue_is_empty(&conn->secondary_list)) {
80
+ pkt = g_queue_pop_head(&conn->secondary_list);
81
+ packet_destroy(pkt, NULL);
82
+ }
83
+}
84
+
85
static void colo_compare_class_init(ObjectClass *oc, void *data)
86
{
87
UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
88
@@ -XXX,XX +XXX,XX @@ static void colo_compare_finalize(Object *obj)
89
qemu_chr_fe_deinit(&s->chr_sec_in);
90
qemu_chr_fe_deinit(&s->chr_out);
91
92
- g_queue_free(&s->conn_list);
93
+ g_main_loop_quit(s->compare_loop);
94
+ qemu_thread_join(&s->thread);
95
96
- if (qemu_thread_is_self(&s->thread)) {
97
- /* compare connection */
98
- g_queue_foreach(&s->conn_list, colo_compare_connection, s);
99
- qemu_thread_join(&s->thread);
100
- }
101
+ /* Release all unhandled packets after compare thead exited */
102
+ g_queue_foreach(&s->conn_list, colo_flush_packets, s);
103
+
104
+ g_queue_free(&s->conn_list);
105
106
+ g_hash_table_destroy(s->connection_track_table);
107
g_free(s->pri_indev);
108
g_free(s->sec_indev);
109
g_free(s->outdev);
110
--
111
2.7.4
112
113
diff view generated by jsdifflib
Deleted patch
1
From: zhanghailiang <zhang.zhanghailiang@huawei.com>
2
1
3
We can call qemu_chr_fe_set_handlers() to add/remove fd been watched
4
in 'context' which can be either default main context or other explicit
5
context. But the original logic is not correct, we didn't remove
6
the right fd because we call g_main_context_find_source_by_id(NULL, tag)
7
which always try to find the Gsource from default context.
8
9
Fix it by passing the right context to g_main_context_find_source_by_id().
10
11
Cc: Paolo Bonzini <pbonzini@redhat.com>
12
Cc: Marc-André Lureau <marcandre.lureau@redhat.com>
13
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
14
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
15
Signed-off-by: Jason Wang <jasowang@redhat.com>
16
---
17
chardev/char-fd.c | 6 +++---
18
chardev/char-io.c | 8 ++++----
19
chardev/char-io.h | 2 +-
20
chardev/char-pty.c | 2 +-
21
chardev/char-socket.c | 4 ++--
22
chardev/char-udp.c | 6 +++---
23
chardev/char.c | 2 +-
24
7 files changed, 15 insertions(+), 15 deletions(-)
25
26
diff --git a/chardev/char-fd.c b/chardev/char-fd.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/chardev/char-fd.c
29
+++ b/chardev/char-fd.c
30
@@ -XXX,XX +XXX,XX @@ static gboolean fd_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
31
ret = qio_channel_read(
32
chan, (gchar *)buf, len, NULL);
33
if (ret == 0) {
34
- remove_fd_in_watch(chr);
35
+ remove_fd_in_watch(chr, NULL);
36
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
37
return FALSE;
38
}
39
@@ -XXX,XX +XXX,XX @@ static void fd_chr_update_read_handler(Chardev *chr,
40
{
41
FDChardev *s = FD_CHARDEV(chr);
42
43
- remove_fd_in_watch(chr);
44
+ remove_fd_in_watch(chr, NULL);
45
if (s->ioc_in) {
46
chr->fd_in_tag = io_add_watch_poll(chr, s->ioc_in,
47
fd_chr_read_poll,
48
@@ -XXX,XX +XXX,XX @@ static void char_fd_finalize(Object *obj)
49
Chardev *chr = CHARDEV(obj);
50
FDChardev *s = FD_CHARDEV(obj);
51
52
- remove_fd_in_watch(chr);
53
+ remove_fd_in_watch(chr, NULL);
54
if (s->ioc_in) {
55
object_unref(OBJECT(s->ioc_in));
56
}
57
diff --git a/chardev/char-io.c b/chardev/char-io.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/chardev/char-io.c
60
+++ b/chardev/char-io.c
61
@@ -XXX,XX +XXX,XX @@ guint io_add_watch_poll(Chardev *chr,
62
return tag;
63
}
64
65
-static void io_remove_watch_poll(guint tag)
66
+static void io_remove_watch_poll(guint tag, GMainContext *context)
67
{
68
GSource *source;
69
IOWatchPoll *iwp;
70
71
g_return_if_fail(tag > 0);
72
73
- source = g_main_context_find_source_by_id(NULL, tag);
74
+ source = g_main_context_find_source_by_id(context, tag);
75
g_return_if_fail(source != NULL);
76
77
iwp = io_watch_poll_from_source(source);
78
@@ -XXX,XX +XXX,XX @@ static void io_remove_watch_poll(guint tag)
79
g_source_destroy(&iwp->parent);
80
}
81
82
-void remove_fd_in_watch(Chardev *chr)
83
+void remove_fd_in_watch(Chardev *chr, GMainContext *context)
84
{
85
if (chr->fd_in_tag) {
86
- io_remove_watch_poll(chr->fd_in_tag);
87
+ io_remove_watch_poll(chr->fd_in_tag, context);
88
chr->fd_in_tag = 0;
89
}
90
}
91
diff --git a/chardev/char-io.h b/chardev/char-io.h
92
index XXXXXXX..XXXXXXX 100644
93
--- a/chardev/char-io.h
94
+++ b/chardev/char-io.h
95
@@ -XXX,XX +XXX,XX @@ guint io_add_watch_poll(Chardev *chr,
96
gpointer user_data,
97
GMainContext *context);
98
99
-void remove_fd_in_watch(Chardev *chr);
100
+void remove_fd_in_watch(Chardev *chr, GMainContext *context);
101
102
int io_channel_send(QIOChannel *ioc, const void *buf, size_t len);
103
104
diff --git a/chardev/char-pty.c b/chardev/char-pty.c
105
index XXXXXXX..XXXXXXX 100644
106
--- a/chardev/char-pty.c
107
+++ b/chardev/char-pty.c
108
@@ -XXX,XX +XXX,XX @@ static void pty_chr_state(Chardev *chr, int connected)
109
g_source_remove(s->open_tag);
110
s->open_tag = 0;
111
}
112
- remove_fd_in_watch(chr);
113
+ remove_fd_in_watch(chr, NULL);
114
s->connected = 0;
115
/* (re-)connect poll interval for idle guests: once per second.
116
* We check more frequently in case the guests sends data to
117
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
118
index XXXXXXX..XXXXXXX 100644
119
--- a/chardev/char-socket.c
120
+++ b/chardev/char-socket.c
121
@@ -XXX,XX +XXX,XX @@ static void tcp_chr_free_connection(Chardev *chr)
122
}
123
124
tcp_set_msgfds(chr, NULL, 0);
125
- remove_fd_in_watch(chr);
126
+ remove_fd_in_watch(chr, NULL);
127
object_unref(OBJECT(s->sioc));
128
s->sioc = NULL;
129
object_unref(OBJECT(s->ioc));
130
@@ -XXX,XX +XXX,XX @@ static void tcp_chr_update_read_handler(Chardev *chr,
131
return;
132
}
133
134
- remove_fd_in_watch(chr);
135
+ remove_fd_in_watch(chr, NULL);
136
if (s->ioc) {
137
chr->fd_in_tag = io_add_watch_poll(chr, s->ioc,
138
tcp_chr_read_poll,
139
diff --git a/chardev/char-udp.c b/chardev/char-udp.c
140
index XXXXXXX..XXXXXXX 100644
141
--- a/chardev/char-udp.c
142
+++ b/chardev/char-udp.c
143
@@ -XXX,XX +XXX,XX @@ static gboolean udp_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
144
ret = qio_channel_read(
145
s->ioc, (char *)s->buf, sizeof(s->buf), NULL);
146
if (ret <= 0) {
147
- remove_fd_in_watch(chr);
148
+ remove_fd_in_watch(chr, NULL);
149
return FALSE;
150
}
151
s->bufcnt = ret;
152
@@ -XXX,XX +XXX,XX @@ static void udp_chr_update_read_handler(Chardev *chr,
153
{
154
UdpChardev *s = UDP_CHARDEV(chr);
155
156
- remove_fd_in_watch(chr);
157
+ remove_fd_in_watch(chr, NULL);
158
if (s->ioc) {
159
chr->fd_in_tag = io_add_watch_poll(chr, s->ioc,
160
udp_chr_read_poll,
161
@@ -XXX,XX +XXX,XX @@ static void char_udp_finalize(Object *obj)
162
Chardev *chr = CHARDEV(obj);
163
UdpChardev *s = UDP_CHARDEV(obj);
164
165
- remove_fd_in_watch(chr);
166
+ remove_fd_in_watch(chr, NULL);
167
if (s->ioc) {
168
object_unref(OBJECT(s->ioc));
169
}
170
diff --git a/chardev/char.c b/chardev/char.c
171
index XXXXXXX..XXXXXXX 100644
172
--- a/chardev/char.c
173
+++ b/chardev/char.c
174
@@ -XXX,XX +XXX,XX @@ void qemu_chr_fe_set_handlers(CharBackend *b,
175
cc = CHARDEV_GET_CLASS(s);
176
if (!opaque && !fd_can_read && !fd_read && !fd_event) {
177
fe_open = 0;
178
- remove_fd_in_watch(s);
179
+ remove_fd_in_watch(s, context);
180
} else {
181
fe_open = 1;
182
}
183
--
184
2.7.4
185
186
diff view generated by jsdifflib
Deleted patch
1
From: zhanghailiang <zhang.zhanghailiang@huawei.com>
2
1
3
We will catch the bellow error report while try to delete compare object
4
by qmp command:
5
chardev/char-io.c:91: io_watch_poll_finalize: Assertion `iwp->src == ((void *)0)' failed.
6
7
This is caused by failing to remove the right fd been watched while
8
call qemu_chr_fe_set_handlers();
9
10
Fix it by pass the worker_context parameter to qemu_chr_fe_set_handlers().
11
12
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
13
Reviewed-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
14
Signed-off-by: Jason Wang <jasowang@redhat.com>
15
---
16
net/colo-compare.c | 20 +++++++++++---------
17
1 file changed, 11 insertions(+), 9 deletions(-)
18
19
diff --git a/net/colo-compare.c b/net/colo-compare.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/net/colo-compare.c
22
+++ b/net/colo-compare.c
23
@@ -XXX,XX +XXX,XX @@ typedef struct CompareState {
24
/* compare thread, a thread for each NIC */
25
QemuThread thread;
26
27
+ GMainContext *worker_context;
28
GMainLoop *compare_loop;
29
} CompareState;
30
31
@@ -XXX,XX +XXX,XX @@ static gboolean check_old_packet_regular(void *opaque)
32
33
static void *colo_compare_thread(void *opaque)
34
{
35
- GMainContext *worker_context;
36
CompareState *s = opaque;
37
GSource *timeout_source;
38
39
- worker_context = g_main_context_new();
40
+ s->worker_context = g_main_context_new();
41
42
qemu_chr_fe_set_handlers(&s->chr_pri_in, compare_chr_can_read,
43
- compare_pri_chr_in, NULL, s, worker_context, true);
44
+ compare_pri_chr_in, NULL, s, s->worker_context, true);
45
qemu_chr_fe_set_handlers(&s->chr_sec_in, compare_chr_can_read,
46
- compare_sec_chr_in, NULL, s, worker_context, true);
47
+ compare_sec_chr_in, NULL, s, s->worker_context, true);
48
49
- s->compare_loop = g_main_loop_new(worker_context, FALSE);
50
+ s->compare_loop = g_main_loop_new(s->worker_context, FALSE);
51
52
/* To kick any packets that the secondary doesn't match */
53
timeout_source = g_timeout_source_new(REGULAR_PACKET_CHECK_MS);
54
g_source_set_callback(timeout_source,
55
(GSourceFunc)check_old_packet_regular, s, NULL);
56
- g_source_attach(timeout_source, worker_context);
57
+ g_source_attach(timeout_source, s->worker_context);
58
59
g_main_loop_run(s->compare_loop);
60
61
g_source_unref(timeout_source);
62
g_main_loop_unref(s->compare_loop);
63
- g_main_context_unref(worker_context);
64
+ g_main_context_unref(s->worker_context);
65
return NULL;
66
}
67
68
@@ -XXX,XX +XXX,XX @@ static void colo_compare_finalize(Object *obj)
69
{
70
CompareState *s = COLO_COMPARE(obj);
71
72
- qemu_chr_fe_deinit(&s->chr_pri_in);
73
- qemu_chr_fe_deinit(&s->chr_sec_in);
74
+ qemu_chr_fe_set_handlers(&s->chr_pri_in, NULL, NULL, NULL, NULL,
75
+ s->worker_context, true);
76
+ qemu_chr_fe_set_handlers(&s->chr_sec_in, NULL, NULL, NULL, NULL,
77
+ s->worker_context, true);
78
qemu_chr_fe_deinit(&s->chr_out);
79
80
g_main_loop_quit(s->compare_loop);
81
--
82
2.7.4
83
84
diff view generated by jsdifflib
Deleted patch
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
2
1
3
We use g_queue_init() to init s->conn_list, so we should use g_queue_clear()
4
to instead of g_queue_free().
5
6
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
7
Reviewed-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
10
net/colo-compare.c | 2 +-
11
1 file changed, 1 insertion(+), 1 deletion(-)
12
13
diff --git a/net/colo-compare.c b/net/colo-compare.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/net/colo-compare.c
16
+++ b/net/colo-compare.c
17
@@ -XXX,XX +XXX,XX @@ static void colo_compare_finalize(Object *obj)
18
/* Release all unhandled packets after compare thead exited */
19
g_queue_foreach(&s->conn_list, colo_flush_packets, s);
20
21
- g_queue_free(&s->conn_list);
22
+ g_queue_clear(&s->conn_list);
23
24
g_hash_table_destroy(s->connection_track_table);
25
g_free(s->pri_indev);
26
--
27
2.7.4
28
29
diff view generated by jsdifflib
Deleted patch
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
2
1
3
The index's in the Vmxnet3Ring were migrated as 32bit ints
4
yet are declared as size_t's. They appear to be derived
5
from 32bit values loaded from guest memory, so actually
6
store them as that.
7
8
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
9
Acked-by: Dmitry Fleytman <dmitry@daynix.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
---
12
hw/net/vmxnet3.c | 12 ++++++------
13
1 file changed, 6 insertions(+), 6 deletions(-)
14
15
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/net/vmxnet3.c
18
+++ b/hw/net/vmxnet3.c
19
@@ -XXX,XX +XXX,XX @@ typedef struct VMXNET3Class {
20
/* Cyclic ring abstraction */
21
typedef struct {
22
hwaddr pa;
23
- size_t size;
24
- size_t cell_size;
25
- size_t next;
26
+ uint32_t size;
27
+ uint32_t cell_size;
28
+ uint32_t next;
29
uint8_t gen;
30
} Vmxnet3Ring;
31
32
static inline void vmxnet3_ring_init(PCIDevice *d,
33
                 Vmxnet3Ring *ring,
34
hwaddr pa,
35
- size_t size,
36
- size_t cell_size,
37
+ uint32_t size,
38
+ uint32_t cell_size,
39
bool zero_region)
40
{
41
ring->pa = pa;
42
@@ -XXX,XX +XXX,XX @@ static inline void vmxnet3_ring_init(PCIDevice *d,
43
}
44
45
#define VMXNET3_RING_DUMP(macro, ring_name, ridx, r) \
46
- macro("%s#%d: base %" PRIx64 " size %zu cell_size %zu gen %d next %zu", \
47
+ macro("%s#%d: base %" PRIx64 " size %u cell_size %u gen %d next %u", \
48
(ring_name), (ridx), \
49
(r)->pa, (r)->size, (r)->cell_size, (r)->gen, (r)->next)
50
51
--
52
2.7.4
53
54
diff view generated by jsdifflib
Deleted patch
1
From: zhanghailiang <zhang.zhanghailiang@huawei.com>
2
1
3
While the offset of packets's sequence for primary side and
4
secondary side is zero, it is unnecessary to call net_checksum_calculate()
5
to recalculate the checksume value of packets.
6
7
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
10
net/filter-rewriter.c | 17 +++++++++++------
11
1 file changed, 11 insertions(+), 6 deletions(-)
12
13
diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/net/filter-rewriter.c
16
+++ b/net/filter-rewriter.c
17
@@ -XXX,XX +XXX,XX @@ static int handle_primary_tcp_pkt(NetFilterState *nf,
18
conn->offset -= (ntohl(tcp_pkt->th_ack) - 1);
19
conn->syn_flag = 0;
20
}
21
- /* handle packets to the secondary from the primary */
22
- tcp_pkt->th_ack = htonl(ntohl(tcp_pkt->th_ack) + conn->offset);
23
+ if (conn->offset) {
24
+ /* handle packets to the secondary from the primary */
25
+ tcp_pkt->th_ack = htonl(ntohl(tcp_pkt->th_ack) + conn->offset);
26
27
- net_checksum_calculate((uint8_t *)pkt->data, pkt->size);
28
+ net_checksum_calculate((uint8_t *)pkt->data, pkt->size);
29
+ }
30
}
31
32
return 0;
33
@@ -XXX,XX +XXX,XX @@ static int handle_secondary_tcp_pkt(NetFilterState *nf,
34
}
35
36
if ((tcp_pkt->th_flags & (TH_ACK | TH_SYN)) == TH_ACK) {
37
- /* handle packets to the primary from the secondary*/
38
- tcp_pkt->th_seq = htonl(ntohl(tcp_pkt->th_seq) - conn->offset);
39
+ /* Only need to adjust seq while offset is Non-zero */
40
+ if (conn->offset) {
41
+ /* handle packets to the primary from the secondary*/
42
+ tcp_pkt->th_seq = htonl(ntohl(tcp_pkt->th_seq) - conn->offset);
43
44
- net_checksum_calculate((uint8_t *)pkt->data, pkt->size);
45
+ net_checksum_calculate((uint8_t *)pkt->data, pkt->size);
46
+ }
47
}
48
49
return 0;
50
--
51
2.7.4
52
53
diff view generated by jsdifflib
Deleted patch
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
2
1
3
Rename colo_packet_compare() to colo_packet_compare_common() that
4
make tcp_compare udp_compare icmp_compare reuse this function.
5
Remove minimum packet size check in icmp_compare, because we have
6
check this in parse_packet_early().
7
8
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
11
net/colo-compare.c | 18 +++++++-----------
12
1 file changed, 7 insertions(+), 11 deletions(-)
13
14
diff --git a/net/colo-compare.c b/net/colo-compare.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/net/colo-compare.c
17
+++ b/net/colo-compare.c
18
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode)
19
* return: 0 means packet same
20
* > 0 || < 0 means packet different
21
*/
22
-static int colo_packet_compare(Packet *ppkt, Packet *spkt)
23
+static int colo_packet_compare_common(Packet *ppkt, Packet *spkt)
24
{
25
trace_colo_compare_ip_info(ppkt->size, inet_ntoa(ppkt->ip->ip_src),
26
inet_ntoa(ppkt->ip->ip_dst), spkt->size,
27
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare(Packet *ppkt, Packet *spkt)
28
if (ppkt->size == spkt->size) {
29
return memcmp(ppkt->data, spkt->data, spkt->size);
30
} else {
31
+ trace_colo_compare_main("Net packet size are not the same");
32
return -1;
33
}
34
}
35
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_tcp(Packet *spkt, Packet *ppkt)
36
int res;
37
38
trace_colo_compare_main("compare tcp");
39
+
40
if (ppkt->size != spkt->size) {
41
if (trace_event_get_state(TRACE_COLO_COMPARE_MISCOMPARE)) {
42
trace_colo_compare_main("pkt size not same");
43
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt)
44
int ret;
45
46
trace_colo_compare_main("compare udp");
47
- ret = colo_packet_compare(ppkt, spkt);
48
+
49
+ ret = colo_packet_compare_common(ppkt, spkt);
50
51
if (ret) {
52
trace_colo_compare_udp_miscompare("primary pkt size", ppkt->size);
53
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt)
54
*/
55
static int colo_packet_compare_icmp(Packet *spkt, Packet *ppkt)
56
{
57
- int network_length;
58
-
59
trace_colo_compare_main("compare icmp");
60
- network_length = ppkt->ip->ip_hl * 4;
61
- if (ppkt->size != spkt->size ||
62
- ppkt->size < network_length + ETH_HLEN) {
63
- return -1;
64
- }
65
66
- if (colo_packet_compare(ppkt, spkt)) {
67
+ if (colo_packet_compare_common(ppkt, spkt)) {
68
trace_colo_compare_icmp_miscompare("primary pkt size",
69
ppkt->size);
70
qemu_hexdump((char *)ppkt->data, stderr, "colo-compare",
71
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_other(Packet *spkt, Packet *ppkt)
72
inet_ntoa(ppkt->ip->ip_dst), spkt->size,
73
inet_ntoa(spkt->ip->ip_src),
74
inet_ntoa(spkt->ip->ip_dst));
75
- return colo_packet_compare(ppkt, spkt);
76
+ return colo_packet_compare_common(ppkt, spkt);
77
}
78
79
static int colo_old_packet_check_one(Packet *pkt, int64_t *check_time)
80
--
81
2.7.4
82
83
diff view generated by jsdifflib