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 |