1
The following changes since commit 2e02083438962d26ef9dcc7100f3b378104183db:
1
The following changes since commit e607bbee553cfe73072870cef458cfa4e78133e2:
2
2
3
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging (2017-11-17 19:08:07 +0000)
3
Merge remote-tracking branch 'remotes/edgar/tags/edgar/xilinx-next-2018-01-26.for-upstream' into staging (2018-01-26 14:24:25 +0000)
4
4
5
are available in the git repository at:
5
are available in the git repository at:
6
6
7
https://github.com/jasowang/qemu.git tags/net-pull-request
7
https://github.com/jasowang/qemu.git tags/net-pull-request
8
8
9
for you to fetch changes up to c527e0afcd7d719abc3a5ca5e4c8ac2fe48b999f:
9
for you to fetch changes up to bf4835a4d5338bb7424827715df22570a8adc67c:
10
10
11
hw/net/vmxnet3: Fix code to work on big endian hosts, too (2017-11-20 11:08:00 +0800)
11
MAINTAINERS: update Dmitry Fleytman email (2018-01-29 16:05:38 +0800)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
14
15
----------------------------------------------------------------
15
----------------------------------------------------------------
16
Ed Swierk (1):
16
Mao Zhongyi (2):
17
net: Transmit zero UDP checksum as 0xFFFF
17
colo: modified the payload compare function
18
colo: compare the packet based on the tcp sequence number
18
19
19
Jason Wang (1):
20
Philippe Mathieu-Daudé (1):
20
Revert "Add new PCI ID for i82559a"
21
MAINTAINERS: update Dmitry Fleytman email
21
22
22
Mao Zhongyi (1):
23
Thomas Huth (3):
23
colo-compare: fix the dangerous assignment
24
net: Allow hubports to connect to other netdevs
25
net: Allow netdevs to be used with 'hostfwd_add' and 'hostfwd_remove'
26
qemu-doc: Get rid of "vlan=X" example in the documentation
24
27
25
Stefan Weil (1):
28
MAINTAINERS | 8 +-
26
MAINTAINERS: Add missing entry for eepro100 emulation
29
hmp-commands.hx | 4 +-
27
30
net/colo-compare.c | 411 +++++++++++++++++++++++++++++++++--------------------
28
Thomas Huth (2):
31
net/colo.c | 9 ++
29
hw/net/eepro100: Fix endianness problem on big endian hosts
32
net/colo.h | 15 ++
30
hw/net/vmxnet3: Fix code to work on big endian hosts, too
33
net/hub.c | 27 +++-
31
34
net/hub.h | 3 +-
32
MAINTAINERS | 5 ++
35
net/net.c | 2 +-
33
hw/net/e1000.c | 2 +-
36
net/slirp.c | 33 +++--
34
hw/net/eepro100.c | 17 +---
37
net/trace-events | 2 +-
35
hw/net/net_rx_pkt.c | 2 +-
38
qapi/net.json | 4 +-
36
hw/net/net_tx_pkt.c | 2 +-
39
qemu-options.hx | 12 +-
37
hw/net/vmware_utils.h | 6 ++
40
12 files changed, 347 insertions(+), 183 deletions(-)
38
hw/net/vmxnet3.c | 49 ++++++++---
39
hw/net/vmxnet3.h | 230 ++++++++++++++++++++++++++++++-------------------
40
include/hw/compat.h | 4 -
41
include/hw/pci/pci.h | 1 -
42
include/net/checksum.h | 6 ++
43
net/colo-compare.c | 2 +-
44
qemu-options.hx | 2 +-
45
13 files changed, 201 insertions(+), 127 deletions(-)
46
41
47
42
diff view generated by jsdifflib
1
From: Ed Swierk <eswierk@skyportsystems.com>
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
2
2
3
The checksum algorithm used by IPv4, TCP and UDP allows a zero value
3
Modified the function colo_packet_compare_common to prepare for the
4
to be represented by either 0x0000 and 0xFFFF. But per RFC 768, a zero
4
tcp packet comparison in the next patch.
5
UDP checksum must be transmitted as 0xFFFF because 0x0000 is a special
6
value meaning no checksum.
7
5
8
Substitute 0xFFFF whenever a checksum is computed as zero when
6
Cc: Zhang Chen <zhangckid@gmail.com>
9
modifying a UDP datagram header. Doing this on IPv4 and TCP checksums
7
Cc: Li Zhijian <lizhijian@cn.fujitsu.com>
10
is unnecessary but legal. Add a wrapper for net_checksum_finish() that
8
Cc: Jason Wang <jasowang@redhat.com>
11
makes the substitution.
12
9
13
(We can't just change net_checksum_finish(), as that function is also
10
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
14
used by receivers to verify checksums, and in that case the expected
11
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
15
value is always 0x0000.)
12
Signed-off-by: Zhang Chen <zhangckid@gmail.com>
16
13
Reviewed-by: Zhang Chen <zhangckid@gmail.com>
17
Signed-off-by: Ed Swierk <eswierk@skyportsystems.com>
18
Signed-off-by: Jason Wang <jasowang@redhat.com>
14
Signed-off-by: Jason Wang <jasowang@redhat.com>
19
---
15
---
20
hw/net/e1000.c | 2 +-
16
net/colo-compare.c | 88 +++++++++++++++++++++++++++---------------------------
21
hw/net/net_rx_pkt.c | 2 +-
17
1 file changed, 44 insertions(+), 44 deletions(-)
22
hw/net/net_tx_pkt.c | 2 +-
23
hw/net/vmxnet3.c | 3 ++-
24
include/net/checksum.h | 6 ++++++
25
5 files changed, 11 insertions(+), 4 deletions(-)
26
18
27
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
19
diff --git a/net/colo-compare.c b/net/colo-compare.c
28
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/net/e1000.c
21
--- a/net/colo-compare.c
30
+++ b/hw/net/e1000.c
22
+++ b/net/colo-compare.c
31
@@ -XXX,XX +XXX,XX @@ putsum(uint8_t *data, uint32_t n, uint32_t sloc, uint32_t css, uint32_t cse)
23
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode, Connection **con)
32
n = cse + 1;
24
* return: 0 means packet same
33
if (sloc < n-1) {
25
* > 0 || < 0 means packet different
34
sum = net_checksum_add(n-css, data+css);
26
*/
35
- stw_be_p(data + sloc, net_checksum_finish(sum));
27
-static int colo_packet_compare_common(Packet *ppkt,
36
+ stw_be_p(data + sloc, net_checksum_finish_nozero(sum));
28
- Packet *spkt,
29
- int poffset,
30
- int soffset)
31
+static int colo_compare_packet_payload(Packet *ppkt,
32
+ Packet *spkt,
33
+ uint16_t poffset,
34
+ uint16_t soffset,
35
+ uint16_t len)
36
+
37
{
38
if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) {
39
char pri_ip_src[20], pri_ip_dst[20], sec_ip_src[20], sec_ip_dst[20];
40
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_common(Packet *ppkt,
41
sec_ip_src, sec_ip_dst);
37
}
42
}
43
44
- poffset = ppkt->vnet_hdr_len + poffset;
45
- soffset = ppkt->vnet_hdr_len + soffset;
46
-
47
- if (ppkt->size - poffset == spkt->size - soffset) {
48
- return memcmp(ppkt->data + poffset,
49
- spkt->data + soffset,
50
- spkt->size - soffset);
51
- } else {
52
- trace_colo_compare_main("Net packet size are not the same");
53
- return -1;
54
- }
55
+ return memcmp(ppkt->data + poffset, spkt->data + soffset, len);
38
}
56
}
39
57
40
diff --git a/hw/net/net_rx_pkt.c b/hw/net/net_rx_pkt.c
58
/*
41
index XXXXXXX..XXXXXXX 100644
59
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_tcp(Packet *spkt, Packet *ppkt)
42
--- a/hw/net/net_rx_pkt.c
60
* the secondary guest's timestamp. COLO just focus on payload,
43
+++ b/hw/net/net_rx_pkt.c
61
* so we just need skip this field.
44
@@ -XXX,XX +XXX,XX @@ _net_rx_pkt_calc_l4_csum(struct NetRxPkt *pkt)
62
*/
45
cntr += net_checksum_add_iov(pkt->vec, pkt->vec_len,
63
- if (ptcp->th_off > 5) {
46
pkt->l4hdr_off, csl, cso);
64
- ptrdiff_t ptcp_offset, stcp_offset;
47
65
48
- csum = net_checksum_finish(cntr);
66
- ptcp_offset = ppkt->transport_header - (uint8_t *)ppkt->data
49
+ csum = net_checksum_finish_nozero(cntr);
67
- + (ptcp->th_off * 4) - ppkt->vnet_hdr_len;
50
68
- stcp_offset = spkt->transport_header - (uint8_t *)spkt->data
51
trace_net_rx_pkt_l4_csum_calc_csum(pkt->l4hdr_off, csl, cntr, csum);
69
- + (stcp->th_off * 4) - spkt->vnet_hdr_len;
52
70
+ ptrdiff_t ptcp_offset, stcp_offset;
53
diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c
71
54
index XXXXXXX..XXXXXXX 100644
72
- /*
55
--- a/hw/net/net_tx_pkt.c
73
- * When network is busy, some tcp options(like sack) will unpredictable
56
+++ b/hw/net/net_tx_pkt.c
74
- * occur in primary side or secondary side. it will make packet size
57
@@ -XXX,XX +XXX,XX @@ static void net_tx_pkt_do_sw_csum(struct NetTxPkt *pkt)
75
- * not same, but the two packet's payload is identical. colo just
58
net_checksum_add_iov(iov, iov_len, pkt->virt_hdr.csum_start, csl, cso);
76
- * care about packet payload, so we skip the option field.
59
77
- */
60
/* Put the checksum obtained into the packet */
78
- res = colo_packet_compare_common(ppkt, spkt, ptcp_offset, stcp_offset);
61
- csum = cpu_to_be16(net_checksum_finish(csum_cntr));
79
- } else if (ptcp->th_sum == stcp->th_sum) {
62
+ csum = cpu_to_be16(net_checksum_finish_nozero(csum_cntr));
80
- res = colo_packet_compare_common(ppkt, spkt, ETH_HLEN, ETH_HLEN);
63
iov_from_buf(iov, iov_len, csum_offset, &csum, sizeof csum);
81
+ ptcp_offset = ppkt->transport_header - (uint8_t *)ppkt->data
82
+ + (ptcp->th_off << 2) - ppkt->vnet_hdr_len;
83
+ stcp_offset = spkt->transport_header - (uint8_t *)spkt->data
84
+ + (stcp->th_off << 2) - spkt->vnet_hdr_len;
85
+ if (ppkt->size - ptcp_offset == spkt->size - stcp_offset) {
86
+ res = colo_compare_packet_payload(ppkt, spkt,
87
+ ptcp_offset, stcp_offset,
88
+ ppkt->size - ptcp_offset);
89
} else {
90
+ trace_colo_compare_main("TCP: payload size of packets are different");
91
res = -1;
92
}
93
94
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_tcp(Packet *spkt, Packet *ppkt)
95
*/
96
static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt)
97
{
98
- int ret;
99
- int network_header_length = ppkt->ip->ip_hl * 4;
100
+ uint16_t network_header_length = ppkt->ip->ip_hl << 2;
101
+ uint16_t offset = network_header_length + ETH_HLEN + ppkt->vnet_hdr_len;
102
103
trace_colo_compare_main("compare udp");
104
105
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt)
106
* other field like TOS,TTL,IP Checksum. we only need to compare
107
* the ip payload here.
108
*/
109
- ret = colo_packet_compare_common(ppkt, spkt,
110
- network_header_length + ETH_HLEN,
111
- network_header_length + ETH_HLEN);
112
-
113
- if (ret) {
114
+ if (ppkt->size != spkt->size) {
115
+ trace_colo_compare_main("UDP: payload size of packets are different");
116
+ return -1;
117
+ }
118
+ if (colo_compare_packet_payload(ppkt, spkt, offset, offset,
119
+ ppkt->size - offset)) {
120
trace_colo_compare_udp_miscompare("primary pkt size", ppkt->size);
121
trace_colo_compare_udp_miscompare("Secondary pkt size", spkt->size);
122
if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) {
123
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt)
124
qemu_hexdump((char *)spkt->data, stderr, "colo-compare sec pkt",
125
spkt->size);
126
}
127
+ return -1;
128
+ } else {
129
+ return 0;
130
}
131
-
132
- return ret;
64
}
133
}
65
134
66
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
135
/*
67
index XXXXXXX..XXXXXXX 100644
136
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt)
68
--- a/hw/net/vmxnet3.c
137
*/
69
+++ b/hw/net/vmxnet3.c
138
static int colo_packet_compare_icmp(Packet *spkt, Packet *ppkt)
70
@@ -XXX,XX +XXX,XX @@ static void vmxnet3_rx_need_csum_calculate(struct NetRxPkt *pkt,
139
{
71
data = (uint8_t *)pkt_data + vhdr->csum_start;
140
- int network_header_length = ppkt->ip->ip_hl * 4;
72
len = pkt_len - vhdr->csum_start;
141
+ uint16_t network_header_length = ppkt->ip->ip_hl << 2;
73
/* Put the checksum obtained into the packet */
142
+ uint16_t offset = network_header_length + ETH_HLEN + ppkt->vnet_hdr_len;
74
- stw_be_p(data + vhdr->csum_offset, net_raw_checksum(data, len));
143
75
+ stw_be_p(data + vhdr->csum_offset,
144
trace_colo_compare_main("compare icmp");
76
+ net_checksum_finish_nozero(net_checksum_add(len, data)));
145
77
146
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_icmp(Packet *spkt, Packet *ppkt)
78
vhdr->flags &= ~VIRTIO_NET_HDR_F_NEEDS_CSUM;
147
* other field like TOS,TTL,IP Checksum. we only need to compare
79
vhdr->flags |= VIRTIO_NET_HDR_F_DATA_VALID;
148
* the ip payload here.
80
diff --git a/include/net/checksum.h b/include/net/checksum.h
149
*/
81
index XXXXXXX..XXXXXXX 100644
150
- if (colo_packet_compare_common(ppkt, spkt,
82
--- a/include/net/checksum.h
151
- network_header_length + ETH_HLEN,
83
+++ b/include/net/checksum.h
152
- network_header_length + ETH_HLEN)) {
84
@@ -XXX,XX +XXX,XX @@ net_checksum_add(int len, uint8_t *buf)
153
+ if (ppkt->size != spkt->size) {
154
+ trace_colo_compare_main("ICMP: payload size of packets are different");
155
+ return -1;
156
+ }
157
+ if (colo_compare_packet_payload(ppkt, spkt, offset, offset,
158
+ ppkt->size - offset)) {
159
trace_colo_compare_icmp_miscompare("primary pkt size",
160
ppkt->size);
161
trace_colo_compare_icmp_miscompare("Secondary pkt size",
162
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_icmp(Packet *spkt, Packet *ppkt)
163
*/
164
static int colo_packet_compare_other(Packet *spkt, Packet *ppkt)
165
{
166
+ uint16_t offset = ppkt->vnet_hdr_len;
167
+
168
trace_colo_compare_main("compare other");
169
if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) {
170
char pri_ip_src[20], pri_ip_dst[20], sec_ip_src[20], sec_ip_dst[20];
171
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_other(Packet *spkt, Packet *ppkt)
172
sec_ip_src, sec_ip_dst);
173
}
174
175
- return colo_packet_compare_common(ppkt, spkt, 0, 0);
176
+ if (ppkt->size != spkt->size) {
177
+ trace_colo_compare_main("Other: payload size of packets are different");
178
+ return -1;
179
+ }
180
+ return colo_compare_packet_payload(ppkt, spkt, offset, offset,
181
+ ppkt->size - offset);
85
}
182
}
86
183
87
static inline uint16_t
184
static int colo_old_packet_check_one(Packet *pkt, int64_t *check_time)
88
+net_checksum_finish_nozero(uint32_t sum)
89
+{
90
+ return net_checksum_finish(sum) ?: 0xFFFF;
91
+}
92
+
93
+static inline uint16_t
94
net_raw_checksum(uint8_t *data, int length)
95
{
96
return net_checksum_finish(net_checksum_add(length, data));
97
--
185
--
98
2.7.4
186
2.7.4
99
187
100
188
diff view generated by jsdifflib
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
2
2
3
Cc: Peter Maydell <peter.maydell@linaro.org>
3
Packet size some time different or when network is busy.
4
Cc: Jason Wang <jasowang@redhat.com>
4
Based on same payload size, but TCP protocol can not
5
guarantee send the same one packet in the same way,
6
7
like that:
8
We send this payload:
9
------------------------------
10
| header |1|2|3|4|5|6|7|8|9|0|
11
------------------------------
12
13
primary:
14
ppkt1:
15
----------------
16
| header |1|2|3|
17
----------------
18
ppkt2:
19
------------------------
20
| header |4|5|6|7|8|9|0|
21
------------------------
22
23
secondary:
24
spkt1:
25
------------------------------
26
| header |1|2|3|4|5|6|7|8|9|0|
27
------------------------------
28
29
In the original method, ppkt1 and ppkt2 are different in size and
30
spkt1, so they can't compare and trigger the checkpoint.
31
32
I have tested FTP get 200M and 1G file many times, I found that
33
the performance was less than 1% of the native.
34
35
Now I reconstructed the comparison of TCP packets based on the
36
TCP sequence number. first of all, ppkt1 and spkt1 have the same
37
starting sequence number, so they can compare, even though their
38
length is different. And then ppkt1 with a smaller payload length
39
is used as the comparison length, if the payload is same, send
40
out the ppkt1 and record the offset(the length of ppkt1 payload)
41
in spkt1. The next comparison, ppkt2 and spkt1 can be compared
42
from the recorded position of spkt1.
43
44
like that:
45
----------------
46
| header |1|2|3| ppkt1
47
---------|-----|
48
| |
49
---------v-----v--------------
50
| header |1|2|3|4|5|6|7|8|9|0| spkt1
51
---------------|\------------|
52
| \offset |
53
---------v-------------v
54
| header |4|5|6|7|8|9|0| ppkt2
55
------------------------
56
57
In this way, the performance can reach native 20% in my multiple
58
tests.
59
5
Cc: Zhang Chen <zhangckid@gmail.com>
60
Cc: Zhang Chen <zhangckid@gmail.com>
6
Cc: Li Zhijian <lizhijian@cn.fujitsu.com>
61
Cc: Li Zhijian <lizhijian@cn.fujitsu.com>
7
Cc: Paolo Bonzini <pbonzini@redhat.com>
62
Cc: Jason Wang <jasowang@redhat.com>
8
Fixes: 8ec14402029d783720f4312ed8a925548e1dad61
63
9
Reported-by: Peter Maydell <peter.maydell@linaro.org>
10
Reported-by: Paolo Bonzini <pbonzini@redhat.com>
11
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
64
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
12
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
65
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
66
Signed-off-by: Zhang Chen <zhangckid@gmail.com>
67
Reviewed-by: Zhang Chen <zhangckid@gmail.com>
68
Tested-by: Zhang Chen <zhangckid@gmail.com>
13
Signed-off-by: Jason Wang <jasowang@redhat.com>
69
Signed-off-by: Jason Wang <jasowang@redhat.com>
14
---
70
---
15
net/colo-compare.c | 2 +-
71
net/colo-compare.c | 343 +++++++++++++++++++++++++++++++++++------------------
16
1 file changed, 1 insertion(+), 1 deletion(-)
72
net/colo.c | 9 ++
73
net/colo.h | 15 +++
74
net/trace-events | 2 +-
75
4 files changed, 250 insertions(+), 119 deletions(-)
17
76
18
diff --git a/net/colo-compare.c b/net/colo-compare.c
77
diff --git a/net/colo-compare.c b/net/colo-compare.c
19
index XXXXXXX..XXXXXXX 100644
78
index XXXXXXX..XXXXXXX 100644
20
--- a/net/colo-compare.c
79
--- a/net/colo-compare.c
21
+++ b/net/colo-compare.c
80
+++ b/net/colo-compare.c
81
@@ -XXX,XX +XXX,XX @@
82
#define COMPARE_READ_LEN_MAX NET_BUFSIZE
83
#define MAX_QUEUE_SIZE 1024
84
85
+#define COLO_COMPARE_FREE_PRIMARY 0x01
86
+#define COLO_COMPARE_FREE_SECONDARY 0x02
87
+
88
/* TODO: Should be configurable */
89
#define REGULAR_PACKET_CHECK_MS 3000
90
91
@@ -XXX,XX +XXX,XX @@ static gint seq_sorter(Packet *a, Packet *b, gpointer data)
92
return ntohl(atcp->th_seq) - ntohl(btcp->th_seq);
93
}
94
95
+static void fill_pkt_tcp_info(void *data, uint32_t *max_ack)
96
+{
97
+ Packet *pkt = data;
98
+ struct tcphdr *tcphd;
99
+
100
+ tcphd = (struct tcphdr *)pkt->transport_header;
101
+
102
+ pkt->tcp_seq = ntohl(tcphd->th_seq);
103
+ pkt->tcp_ack = ntohl(tcphd->th_ack);
104
+ *max_ack = *max_ack > pkt->tcp_ack ? *max_ack : pkt->tcp_ack;
105
+ pkt->header_size = pkt->transport_header - (uint8_t *)pkt->data
106
+ + (tcphd->th_off << 2) - pkt->vnet_hdr_len;
107
+ pkt->payload_size = pkt->size - pkt->header_size;
108
+ pkt->seq_end = pkt->tcp_seq + pkt->payload_size;
109
+ pkt->flags = tcphd->th_flags;
110
+}
111
+
112
/*
113
* Return 1 on success, if return 0 means the
114
* packet will be dropped
115
*/
116
-static int colo_insert_packet(GQueue *queue, Packet *pkt)
117
+static int colo_insert_packet(GQueue *queue, Packet *pkt, uint32_t *max_ack)
118
{
119
if (g_queue_get_length(queue) <= MAX_QUEUE_SIZE) {
120
if (pkt->ip->ip_p == IPPROTO_TCP) {
121
+ fill_pkt_tcp_info(pkt, max_ack);
122
g_queue_insert_sorted(queue,
123
pkt,
124
(GCompareDataFunc)seq_sorter,
22
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode, Connection **con)
125
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode, Connection **con)
126
}
127
128
if (mode == PRIMARY_IN) {
129
- if (!colo_insert_packet(&conn->primary_list, pkt)) {
130
+ if (!colo_insert_packet(&conn->primary_list, pkt, &conn->pack)) {
131
error_report("colo compare primary queue size too big,"
23
"drop packet");
132
"drop packet");
24
}
133
}
134
} else {
135
- if (!colo_insert_packet(&conn->secondary_list, pkt)) {
136
+ if (!colo_insert_packet(&conn->secondary_list, pkt, &conn->sack)) {
137
error_report("colo compare secondary queue size too big,"
138
"drop packet");
139
}
140
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode, Connection **con)
141
return 0;
142
}
143
144
+static inline bool after(uint32_t seq1, uint32_t seq2)
145
+{
146
+ return (int32_t)(seq1 - seq2) > 0;
147
+}
148
+
149
+static void colo_release_primary_pkt(CompareState *s, Packet *pkt)
150
+{
151
+ int ret;
152
+ ret = compare_chr_send(s,
153
+ pkt->data,
154
+ pkt->size,
155
+ pkt->vnet_hdr_len);
156
+ if (ret < 0) {
157
+ error_report("colo send primary packet failed");
158
+ }
159
+ trace_colo_compare_main("packet same and release packet");
160
+ packet_destroy(pkt, NULL);
161
+}
162
+
163
/*
164
* The IP packets sent by primary and secondary
165
* will be compared in here
166
@@ -XXX,XX +XXX,XX @@ static int colo_compare_packet_payload(Packet *ppkt,
167
}
168
169
/*
170
- * Called from the compare thread on the primary
171
- * for compare tcp packet
172
- * compare_tcp copied from Dr. David Alan Gilbert's branch
173
- */
174
-static int colo_packet_compare_tcp(Packet *spkt, Packet *ppkt)
175
+ * return true means that the payload is consist and
176
+ * need to make the next comparison, false means do
177
+ * the checkpoint
178
+*/
179
+static bool colo_mark_tcp_pkt(Packet *ppkt, Packet *spkt,
180
+ int8_t *mark, uint32_t max_ack)
181
{
182
- struct tcphdr *ptcp, *stcp;
183
- int res;
184
+ *mark = 0;
185
+
186
+ if (ppkt->tcp_seq == spkt->tcp_seq && ppkt->seq_end == spkt->seq_end) {
187
+ if (colo_compare_packet_payload(ppkt, spkt,
188
+ ppkt->header_size, spkt->header_size,
189
+ ppkt->payload_size)) {
190
+ *mark = COLO_COMPARE_FREE_SECONDARY | COLO_COMPARE_FREE_PRIMARY;
191
+ return true;
192
+ }
193
+ }
194
+ if (ppkt->tcp_seq == spkt->tcp_seq && ppkt->seq_end == spkt->seq_end) {
195
+ if (colo_compare_packet_payload(ppkt, spkt,
196
+ ppkt->header_size, spkt->header_size,
197
+ ppkt->payload_size)) {
198
+ *mark = COLO_COMPARE_FREE_SECONDARY | COLO_COMPARE_FREE_PRIMARY;
199
+ return true;
200
+ }
201
+ }
202
+
203
+ /* one part of secondary packet payload still need to be compared */
204
+ if (!after(ppkt->seq_end, spkt->seq_end)) {
205
+ if (colo_compare_packet_payload(ppkt, spkt,
206
+ ppkt->header_size + ppkt->offset,
207
+ spkt->header_size + spkt->offset,
208
+ ppkt->payload_size - ppkt->offset)) {
209
+ if (!after(ppkt->tcp_ack, max_ack)) {
210
+ *mark = COLO_COMPARE_FREE_PRIMARY;
211
+ spkt->offset += ppkt->payload_size - ppkt->offset;
212
+ return true;
213
+ } else {
214
+ /* secondary guest hasn't ack the data, don't send
215
+ * out this packet
216
+ */
217
+ return false;
218
+ }
219
+ }
220
+ } else {
221
+ /* primary packet is longer than secondary packet, compare
222
+ * the same part and mark the primary packet offset
223
+ */
224
+ if (colo_compare_packet_payload(ppkt, spkt,
225
+ ppkt->header_size + ppkt->offset,
226
+ spkt->header_size + spkt->offset,
227
+ spkt->payload_size - spkt->offset)) {
228
+ *mark = COLO_COMPARE_FREE_SECONDARY;
229
+ ppkt->offset += spkt->payload_size - spkt->offset;
230
+ return true;
231
+ }
232
+ }
233
234
- trace_colo_compare_main("compare tcp");
235
+ return false;
236
+}
237
238
- ptcp = (struct tcphdr *)ppkt->transport_header;
239
- stcp = (struct tcphdr *)spkt->transport_header;
240
+static void colo_compare_tcp(CompareState *s, Connection *conn)
241
+{
242
+ Packet *ppkt = NULL, *spkt = NULL;
243
+ int8_t mark;
244
245
/*
246
- * The 'identification' field in the IP header is *very* random
247
- * it almost never matches. Fudge this by ignoring differences in
248
- * unfragmented packets; they'll normally sort themselves out if different
249
- * anyway, and it should recover at the TCP level.
250
- * An alternative would be to get both the primary and secondary to rewrite
251
- * somehow; but that would need some sync traffic to sync the state
252
- */
253
- if (ntohs(ppkt->ip->ip_off) & IP_DF) {
254
- spkt->ip->ip_id = ppkt->ip->ip_id;
255
- /* and the sum will be different if the IDs were different */
256
- spkt->ip->ip_sum = ppkt->ip->ip_sum;
257
+ * If ppkt and spkt have the same payload, but ppkt's ACK
258
+ * is greater than spkt's ACK, in this case we can not
259
+ * send the ppkt because it will cause the secondary guest
260
+ * to miss sending some data in the next. Therefore, we
261
+ * record the maximum ACK in the current queue at both
262
+ * primary side and secondary side. Only when the ack is
263
+ * less than the smaller of the two maximum ack, then we
264
+ * can ensure that the packet's payload is acknowledged by
265
+ * primary and secondary.
266
+ */
267
+ uint32_t min_ack = conn->pack > conn->sack ? conn->sack : conn->pack;
268
+
269
+pri:
270
+ if (g_queue_is_empty(&conn->primary_list)) {
271
+ return;
25
}
272
}
26
- con = &conn;
273
+ ppkt = g_queue_pop_head(&conn->primary_list);
27
+ *con = conn;
274
+sec:
28
275
+ if (g_queue_is_empty(&conn->secondary_list)) {
29
return 0;
276
+ g_queue_push_head(&conn->primary_list, ppkt);
30
}
277
+ return;
278
+ }
279
+ spkt = g_queue_pop_head(&conn->secondary_list);
280
281
- /*
282
- * Check tcp header length for tcp option field.
283
- * th_off > 5 means this tcp packet have options field.
284
- * The tcp options maybe always different.
285
- * for example:
286
- * From RFC 7323.
287
- * TCP Timestamps option (TSopt):
288
- * Kind: 8
289
- *
290
- * Length: 10 bytes
291
- *
292
- * +-------+-------+---------------------+---------------------+
293
- * |Kind=8 | 10 | TS Value (TSval) |TS Echo Reply (TSecr)|
294
- * +-------+-------+---------------------+---------------------+
295
- * 1 1 4 4
296
- *
297
- * In this case the primary guest's timestamp always different with
298
- * the secondary guest's timestamp. COLO just focus on payload,
299
- * so we just need skip this field.
300
- */
301
+ if (ppkt->tcp_seq == ppkt->seq_end) {
302
+ colo_release_primary_pkt(s, ppkt);
303
+ ppkt = NULL;
304
+ }
305
306
- ptrdiff_t ptcp_offset, stcp_offset;
307
+ if (ppkt && conn->compare_seq && !after(ppkt->seq_end, conn->compare_seq)) {
308
+ trace_colo_compare_main("pri: this packet has compared");
309
+ colo_release_primary_pkt(s, ppkt);
310
+ ppkt = NULL;
311
+ }
312
313
- ptcp_offset = ppkt->transport_header - (uint8_t *)ppkt->data
314
- + (ptcp->th_off << 2) - ppkt->vnet_hdr_len;
315
- stcp_offset = spkt->transport_header - (uint8_t *)spkt->data
316
- + (stcp->th_off << 2) - spkt->vnet_hdr_len;
317
- if (ppkt->size - ptcp_offset == spkt->size - stcp_offset) {
318
- res = colo_compare_packet_payload(ppkt, spkt,
319
- ptcp_offset, stcp_offset,
320
- ppkt->size - ptcp_offset);
321
+ if (spkt->tcp_seq == spkt->seq_end) {
322
+ packet_destroy(spkt, NULL);
323
+ if (!ppkt) {
324
+ goto pri;
325
+ } else {
326
+ goto sec;
327
+ }
328
} else {
329
- trace_colo_compare_main("TCP: payload size of packets are different");
330
- res = -1;
331
+ if (conn->compare_seq && !after(spkt->seq_end, conn->compare_seq)) {
332
+ trace_colo_compare_main("sec: this packet has compared");
333
+ packet_destroy(spkt, NULL);
334
+ if (!ppkt) {
335
+ goto pri;
336
+ } else {
337
+ goto sec;
338
+ }
339
+ }
340
+ if (!ppkt) {
341
+ g_queue_push_head(&conn->secondary_list, spkt);
342
+ goto pri;
343
+ }
344
}
345
346
- if (res != 0 &&
347
- trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) {
348
- char pri_ip_src[20], pri_ip_dst[20], sec_ip_src[20], sec_ip_dst[20];
349
-
350
- strcpy(pri_ip_src, inet_ntoa(ppkt->ip->ip_src));
351
- strcpy(pri_ip_dst, inet_ntoa(ppkt->ip->ip_dst));
352
- strcpy(sec_ip_src, inet_ntoa(spkt->ip->ip_src));
353
- strcpy(sec_ip_dst, inet_ntoa(spkt->ip->ip_dst));
354
-
355
- trace_colo_compare_ip_info(ppkt->size, pri_ip_src,
356
- pri_ip_dst, spkt->size,
357
- sec_ip_src, sec_ip_dst);
358
-
359
- trace_colo_compare_tcp_info("pri tcp packet",
360
- ntohl(ptcp->th_seq),
361
- ntohl(ptcp->th_ack),
362
- res, ptcp->th_flags,
363
- ppkt->size);
364
-
365
- trace_colo_compare_tcp_info("sec tcp packet",
366
- ntohl(stcp->th_seq),
367
- ntohl(stcp->th_ack),
368
- res, stcp->th_flags,
369
- spkt->size);
370
+ if (colo_mark_tcp_pkt(ppkt, spkt, &mark, min_ack)) {
371
+ trace_colo_compare_tcp_info("pri",
372
+ ppkt->tcp_seq, ppkt->tcp_ack,
373
+ ppkt->header_size, ppkt->payload_size,
374
+ ppkt->offset, ppkt->flags);
375
+
376
+ trace_colo_compare_tcp_info("sec",
377
+ spkt->tcp_seq, spkt->tcp_ack,
378
+ spkt->header_size, spkt->payload_size,
379
+ spkt->offset, spkt->flags);
380
+
381
+ if (mark == COLO_COMPARE_FREE_PRIMARY) {
382
+ conn->compare_seq = ppkt->seq_end;
383
+ colo_release_primary_pkt(s, ppkt);
384
+ g_queue_push_head(&conn->secondary_list, spkt);
385
+ goto pri;
386
+ }
387
+ if (mark == COLO_COMPARE_FREE_SECONDARY) {
388
+ conn->compare_seq = spkt->seq_end;
389
+ packet_destroy(spkt, NULL);
390
+ goto sec;
391
+ }
392
+ if (mark == (COLO_COMPARE_FREE_PRIMARY | COLO_COMPARE_FREE_SECONDARY)) {
393
+ conn->compare_seq = ppkt->seq_end;
394
+ colo_release_primary_pkt(s, ppkt);
395
+ packet_destroy(spkt, NULL);
396
+ goto pri;
397
+ }
398
+ } else {
399
+ g_queue_push_head(&conn->primary_list, ppkt);
400
+ g_queue_push_head(&conn->secondary_list, spkt);
401
402
qemu_hexdump((char *)ppkt->data, stderr,
403
"colo-compare ppkt", ppkt->size);
404
qemu_hexdump((char *)spkt->data, stderr,
405
"colo-compare spkt", spkt->size);
406
- }
407
408
- return res;
409
+ /*
410
+ * colo_compare_inconsistent_notify();
411
+ * TODO: notice to checkpoint();
412
+ */
413
+ }
414
}
415
416
+
417
/*
418
* Called from the compare thread on the primary
419
* for compare udp packet
420
@@ -XXX,XX +XXX,XX @@ static void colo_old_packet_check(void *opaque)
421
(GCompareFunc)colo_old_packet_check_one_conn);
422
}
423
424
-/*
425
- * Called from the compare thread on the primary
426
- * for compare packet with secondary list of the
427
- * specified connection when a new packet was
428
- * queued to it.
429
- */
430
-static void colo_compare_connection(void *opaque, void *user_data)
431
+static void colo_compare_packet(CompareState *s, Connection *conn,
432
+ int (*HandlePacket)(Packet *spkt,
433
+ Packet *ppkt))
434
{
435
- CompareState *s = user_data;
436
- Connection *conn = opaque;
437
Packet *pkt = NULL;
438
GList *result = NULL;
439
- int ret;
440
441
while (!g_queue_is_empty(&conn->primary_list) &&
442
!g_queue_is_empty(&conn->secondary_list)) {
443
pkt = g_queue_pop_head(&conn->primary_list);
444
- switch (conn->ip_proto) {
445
- case IPPROTO_TCP:
446
- result = g_queue_find_custom(&conn->secondary_list,
447
- pkt, (GCompareFunc)colo_packet_compare_tcp);
448
- break;
449
- case IPPROTO_UDP:
450
- result = g_queue_find_custom(&conn->secondary_list,
451
- pkt, (GCompareFunc)colo_packet_compare_udp);
452
- break;
453
- case IPPROTO_ICMP:
454
- result = g_queue_find_custom(&conn->secondary_list,
455
- pkt, (GCompareFunc)colo_packet_compare_icmp);
456
- break;
457
- default:
458
- result = g_queue_find_custom(&conn->secondary_list,
459
- pkt, (GCompareFunc)colo_packet_compare_other);
460
- break;
461
- }
462
+ result = g_queue_find_custom(&conn->secondary_list,
463
+ pkt, (GCompareFunc)HandlePacket);
464
465
if (result) {
466
- ret = compare_chr_send(s,
467
- pkt->data,
468
- pkt->size,
469
- pkt->vnet_hdr_len);
470
- if (ret < 0) {
471
- error_report("colo_send_primary_packet failed");
472
- }
473
- trace_colo_compare_main("packet same and release packet");
474
+ colo_release_primary_pkt(s, pkt);
475
g_queue_remove(&conn->secondary_list, result->data);
476
- packet_destroy(pkt, NULL);
477
} else {
478
/*
479
* If one packet arrive late, the secondary_list or
480
@@ -XXX,XX +XXX,XX @@ static void colo_compare_connection(void *opaque, void *user_data)
481
}
482
}
483
484
+/*
485
+ * Called from the compare thread on the primary
486
+ * for compare packet with secondary list of the
487
+ * specified connection when a new packet was
488
+ * queued to it.
489
+ */
490
+static void colo_compare_connection(void *opaque, void *user_data)
491
+{
492
+ CompareState *s = user_data;
493
+ Connection *conn = opaque;
494
+
495
+ switch (conn->ip_proto) {
496
+ case IPPROTO_TCP:
497
+ colo_compare_tcp(s, conn);
498
+ break;
499
+ case IPPROTO_UDP:
500
+ colo_compare_packet(s, conn, colo_packet_compare_udp);
501
+ break;
502
+ case IPPROTO_ICMP:
503
+ colo_compare_packet(s, conn, colo_packet_compare_icmp);
504
+ break;
505
+ default:
506
+ colo_compare_packet(s, conn, colo_packet_compare_other);
507
+ break;
508
+ }
509
+}
510
+
511
static int compare_chr_send(CompareState *s,
512
const uint8_t *buf,
513
uint32_t size,
514
diff --git a/net/colo.c b/net/colo.c
515
index XXXXXXX..XXXXXXX 100644
516
--- a/net/colo.c
517
+++ b/net/colo.c
518
@@ -XXX,XX +XXX,XX @@ Connection *connection_new(ConnectionKey *key)
519
conn->processing = false;
520
conn->offset = 0;
521
conn->syn_flag = 0;
522
+ conn->pack = 0;
523
+ conn->sack = 0;
524
g_queue_init(&conn->primary_list);
525
g_queue_init(&conn->secondary_list);
526
527
@@ -XXX,XX +XXX,XX @@ Packet *packet_new(const void *data, int size, int vnet_hdr_len)
528
pkt->size = size;
529
pkt->creation_ms = qemu_clock_get_ms(QEMU_CLOCK_HOST);
530
pkt->vnet_hdr_len = vnet_hdr_len;
531
+ pkt->tcp_seq = 0;
532
+ pkt->tcp_ack = 0;
533
+ pkt->seq_end = 0;
534
+ pkt->header_size = 0;
535
+ pkt->payload_size = 0;
536
+ pkt->offset = 0;
537
+ pkt->flags = 0;
538
539
return pkt;
540
}
541
diff --git a/net/colo.h b/net/colo.h
542
index XXXXXXX..XXXXXXX 100644
543
--- a/net/colo.h
544
+++ b/net/colo.h
545
@@ -XXX,XX +XXX,XX @@ typedef struct Packet {
546
int64_t creation_ms;
547
/* Get vnet_hdr_len from filter */
548
uint32_t vnet_hdr_len;
549
+ uint32_t tcp_seq; /* sequence number */
550
+ uint32_t tcp_ack; /* acknowledgement number */
551
+ /* the sequence number of the last byte of the packet */
552
+ uint32_t seq_end;
553
+ uint8_t header_size; /* the header length */
554
+ uint16_t payload_size; /* the payload length */
555
+ /* record the payload offset(the length that has been compared) */
556
+ uint16_t offset;
557
+ uint8_t flags; /* Flags(aka Control bits) */
558
} Packet;
559
560
typedef struct ConnectionKey {
561
@@ -XXX,XX +XXX,XX @@ typedef struct Connection {
562
/* flag to enqueue unprocessed_connections */
563
bool processing;
564
uint8_t ip_proto;
565
+ /* record the sequence number that has been compared */
566
+ uint32_t compare_seq;
567
+ /* the maximum of acknowledgement number in primary_list queue */
568
+ uint32_t pack;
569
+ /* the maximum of acknowledgement number in secondary_list queue */
570
+ uint32_t sack;
571
/* offset = secondary_seq - primary_seq */
572
tcp_seq offset;
573
/*
574
diff --git a/net/trace-events b/net/trace-events
575
index XXXXXXX..XXXXXXX 100644
576
--- a/net/trace-events
577
+++ b/net/trace-events
578
@@ -XXX,XX +XXX,XX @@ colo_compare_icmp_miscompare(const char *sta, int size) ": %s = %d"
579
colo_compare_ip_info(int psize, const char *sta, const char *stb, int ssize, const char *stc, const char *std) "ppkt size = %d, ip_src = %s, ip_dst = %s, spkt size = %d, ip_src = %s, ip_dst = %s"
580
colo_old_packet_check_found(int64_t old_time) "%" PRId64
581
colo_compare_miscompare(void) ""
582
-colo_compare_tcp_info(const char *pkt, uint32_t seq, uint32_t ack, int res, uint32_t flag, int size) "side: %s seq/ack= %u/%u res= %d flags= 0x%x pkt_size: %d\n"
583
+colo_compare_tcp_info(const char *pkt, uint32_t seq, uint32_t ack, int hdlen, int pdlen, int offset, int flags) "%s: seq/ack= %u/%u hdlen= %d pdlen= %d offset= %d flags=%d\n"
584
585
# net/filter-rewriter.c
586
colo_filter_rewriter_debug(void) ""
31
--
587
--
32
2.7.4
588
2.7.4
33
589
34
590
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
Since commit ab06ec43577177a442e8 we test the vmxnet3 device in the
3
QEMU can emulate hubs to connect NICs and netdevs. This is currently
4
pxe-tester, too (when running "make check SPEED=slow"). This now
4
primarily used for the mis-named 'vlan' feature of the networking
5
revealed that the code is not working there if the host is a big
5
subsystem. Now the 'vlan' feature has been marked as deprecated, since
6
endian machine (for example ppc64 or s390x) - "make check SPEED=slow"
6
its name is rather confusing and the users often rather mis-configure
7
is now failing on such hosts.
7
their network when trying to use it. But while the 'vlan' parameter
8
8
should be removed at one point in time, the basic idea of emulating
9
The vmxnet3 code lacks endianness conversions in a couple of places.
9
a hub in QEMU is still good: It's useful for bundling up the output of
10
Interestingly, the bitfields in the structs in vmxnet3.h already tried to
10
multiple NICs into one single l2tp netdev for example.
11
take care of the *bit* endianness of the C compilers - but the code missed
11
12
to change the *byte* endianness when reading or writing the corresponding
12
Now to be able to use the hubport feature without 'vlan's, there is one
13
structs. So the bitfields are now wrapped into unions which allow to change
13
missing piece: The possibility to connect a hubport to a netdev, too.
14
the byte endianness during runtime with the non-bitfield member of the union.
14
This patch adds this possibility by introducing a new "netdev=..."
15
With these changes, "make check SPEED=slow" now properly works on big endian
15
parameter to the hubports.
16
hosts, too.
16
17
17
To bundle up the output of multiple NICs into one socket netdev, you can
18
Reported-by: David Gibson <dgibson@redhat.com>
18
now run QEMU with these parameters for example:
19
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
20
Reviewed-by: David Gibson <dgibson@redhat.com>
20
qemu-system-ppc64 ... -netdev socket,id=s1,connect=:11122 \
21
-netdev hubport,hubid=1,id=h1,netdev=s1 \
22
-netdev hubport,hubid=1,id=h2 -device e1000,netdev=h2 \
23
-netdev hubport,hubid=1,id=h3 -device virtio-net-pci,netdev=h3
24
25
For using the socket netdev, you have got to start another QEMU as the
26
receiving side first, for example with network dumping enabled:
27
28
qemu-system-x86_64 -M isapc -netdev socket,id=s0,listen=:11122 \
29
-device ne2k_isa,netdev=s0 \
30
-object filter-dump,id=f1,netdev=s0,file=/tmp/dump.dat
31
32
After the ppc64 guest tried to boot from both NICs, you can see in the
33
dump file (using Wireshark, for example), that the output of both NICs
34
(the e1000 and the virtio-net-pci) has been successfully transfered
35
via the socket netdev in this case.
36
37
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
21
Signed-off-by: Thomas Huth <thuth@redhat.com>
38
Signed-off-by: Thomas Huth <thuth@redhat.com>
22
Signed-off-by: Jason Wang <jasowang@redhat.com>
39
Signed-off-by: Jason Wang <jasowang@redhat.com>
23
---
40
---
24
hw/net/vmware_utils.h | 6 ++
41
net/hub.c | 27 +++++++++++++++++++++------
25
hw/net/vmxnet3.c | 46 +++++++---
42
net/hub.h | 3 ++-
26
hw/net/vmxnet3.h | 230 ++++++++++++++++++++++++++++++--------------------
43
net/net.c | 2 +-
27
3 files changed, 181 insertions(+), 101 deletions(-)
44
qapi/net.json | 4 +++-
28
45
qemu-options.hx | 8 +++++---
29
diff --git a/hw/net/vmware_utils.h b/hw/net/vmware_utils.h
46
5 files changed, 32 insertions(+), 12 deletions(-)
30
index XXXXXXX..XXXXXXX 100644
47
31
--- a/hw/net/vmware_utils.h
48
diff --git a/net/hub.c b/net/hub.c
32
+++ b/hw/net/vmware_utils.h
49
index XXXXXXX..XXXXXXX 100644
33
@@ -XXX,XX +XXX,XX @@ vmw_shmem_ld16(PCIDevice *d, hwaddr addr)
50
--- a/net/hub.c
51
+++ b/net/hub.c
52
@@ -XXX,XX +XXX,XX @@
53
*/
54
55
#include "qemu/osdep.h"
56
+#include "qapi/error.h"
57
#include "monitor/monitor.h"
58
#include "net/net.h"
59
#include "clients.h"
60
@@ -XXX,XX +XXX,XX @@ static NetClientInfo net_hub_port_info = {
61
.cleanup = net_hub_port_cleanup,
62
};
63
64
-static NetHubPort *net_hub_port_new(NetHub *hub, const char *name)
65
+static NetHubPort *net_hub_port_new(NetHub *hub, const char *name,
66
+ NetClientState *hubpeer)
34
{
67
{
35
uint16_t res;
68
NetClientState *nc;
36
pci_dma_read(d, addr, &res, 2);
69
NetHubPort *port;
37
+ res = le16_to_cpu(res);
70
@@ -XXX,XX +XXX,XX @@ static NetHubPort *net_hub_port_new(NetHub *hub, const char *name)
38
VMW_SHPRN("SHMEM load16: %" PRIx64 " (value 0x%X)", addr, res);
71
name = default_name;
39
return res;
72
}
73
74
- nc = qemu_new_net_client(&net_hub_port_info, NULL, "hub", name);
75
+ nc = qemu_new_net_client(&net_hub_port_info, hubpeer, "hub", name);
76
port = DO_UPCAST(NetHubPort, nc, nc);
77
port->id = id;
78
port->hub = hub;
79
@@ -XXX,XX +XXX,XX @@ static NetHubPort *net_hub_port_new(NetHub *hub, const char *name)
80
81
/**
82
* Create a port on a given hub
83
+ * @hub_id: Number of the hub
84
* @name: Net client name or NULL for default name.
85
+ * @hubpeer: Peer to use (if "netdev=id" has been specified)
86
*
87
* If there is no existing hub with the given id then a new hub is created.
88
*/
89
-NetClientState *net_hub_add_port(int hub_id, const char *name)
90
+NetClientState *net_hub_add_port(int hub_id, const char *name,
91
+ NetClientState *hubpeer)
92
{
93
NetHub *hub;
94
NetHubPort *port;
95
@@ -XXX,XX +XXX,XX @@ NetClientState *net_hub_add_port(int hub_id, const char *name)
96
hub = net_hub_new(hub_id);
97
}
98
99
- port = net_hub_port_new(hub, name);
100
+ port = net_hub_port_new(hub, name, hubpeer);
101
return &port->nc;
40
}
102
}
41
@@ -XXX,XX +XXX,XX @@ static inline void
103
42
vmw_shmem_st16(PCIDevice *d, hwaddr addr, uint16_t value)
104
@@ -XXX,XX +XXX,XX @@ NetClientState *net_hub_port_find(int hub_id)
105
}
106
}
107
108
- nc = net_hub_add_port(hub_id, NULL);
109
+ nc = net_hub_add_port(hub_id, NULL, NULL);
110
return nc;
111
}
112
113
@@ -XXX,XX +XXX,XX @@ int net_init_hubport(const Netdev *netdev, const char *name,
114
NetClientState *peer, Error **errp)
43
{
115
{
44
VMW_SHPRN("SHMEM store16: %" PRIx64 " (value 0x%X)", addr, value);
116
const NetdevHubPortOptions *hubport;
45
+ value = cpu_to_le16(value);
117
+ NetClientState *hubpeer = NULL;
46
pci_dma_write(d, addr, &value, 2);
118
119
assert(netdev->type == NET_CLIENT_DRIVER_HUBPORT);
120
assert(!peer);
121
hubport = &netdev->u.hubport;
122
123
- net_hub_add_port(hubport->hubid, name);
124
+ if (hubport->has_netdev) {
125
+ hubpeer = qemu_find_netdev(hubport->netdev);
126
+ if (!hubpeer) {
127
+ error_setg(errp, "netdev '%s' not found", hubport->netdev);
128
+ return -1;
129
+ }
130
+ }
131
+
132
+ net_hub_add_port(hubport->hubid, name, hubpeer);
133
+
134
return 0;
47
}
135
}
48
136
49
@@ -XXX,XX +XXX,XX @@ vmw_shmem_ld32(PCIDevice *d, hwaddr addr)
137
diff --git a/net/hub.h b/net/hub.h
50
{
138
index XXXXXXX..XXXXXXX 100644
51
uint32_t res;
139
--- a/net/hub.h
52
pci_dma_read(d, addr, &res, 4);
140
+++ b/net/hub.h
53
+ res = le32_to_cpu(res);
141
@@ -XXX,XX +XXX,XX @@
54
VMW_SHPRN("SHMEM load32: %" PRIx64 " (value 0x%X)", addr, res);
142
55
return res;
143
#include "qemu-common.h"
56
}
144
57
@@ -XXX,XX +XXX,XX @@ static inline void
145
-NetClientState *net_hub_add_port(int hub_id, const char *name);
58
vmw_shmem_st32(PCIDevice *d, hwaddr addr, uint32_t value)
146
+NetClientState *net_hub_add_port(int hub_id, const char *name,
59
{
147
+ NetClientState *hubpeer);
60
VMW_SHPRN("SHMEM store32: %" PRIx64 " (value 0x%X)", addr, value);
148
NetClientState *net_hub_find_client_by_name(int hub_id, const char *name);
61
+ value = cpu_to_le32(value);
149
void net_hub_info(Monitor *mon);
62
pci_dma_write(d, addr, &value, 4);
150
void net_hub_check_clients(void);
63
}
151
diff --git a/net/net.c b/net/net.c
64
152
index XXXXXXX..XXXXXXX 100644
65
@@ -XXX,XX +XXX,XX @@ vmw_shmem_ld64(PCIDevice *d, hwaddr addr)
153
--- a/net/net.c
66
{
154
+++ b/net/net.c
67
uint64_t res;
155
@@ -XXX,XX +XXX,XX @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp)
68
pci_dma_read(d, addr, &res, 8);
156
/* Do not add to a vlan if it's a nic with a netdev= parameter. */
69
+ res = le64_to_cpu(res);
157
if (netdev->type != NET_CLIENT_DRIVER_NIC ||
70
VMW_SHPRN("SHMEM load64: %" PRIx64 " (value %" PRIx64 ")", addr, res);
158
!opts->u.nic.has_netdev) {
71
return res;
159
- peer = net_hub_add_port(net->has_vlan ? net->vlan : 0, NULL);
72
}
160
+ peer = net_hub_add_port(net->has_vlan ? net->vlan : 0, NULL, NULL);
73
@@ -XXX,XX +XXX,XX @@ static inline void
74
vmw_shmem_st64(PCIDevice *d, hwaddr addr, uint64_t value)
75
{
76
VMW_SHPRN("SHMEM store64: %" PRIx64 " (value %" PRIx64 ")", addr, value);
77
+ value = cpu_to_le64(value);
78
pci_dma_write(d, addr, &value, 8);
79
}
80
81
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
82
index XXXXXXX..XXXXXXX 100644
83
--- a/hw/net/vmxnet3.c
84
+++ b/hw/net/vmxnet3.c
85
@@ -XXX,XX +XXX,XX @@ vmxnet3_dump_tx_descr(struct Vmxnet3_TxDesc *descr)
86
"addr %" PRIx64 ", len: %d, gen: %d, rsvd: %d, "
87
"dtype: %d, ext1: %d, msscof: %d, hlen: %d, om: %d, "
88
"eop: %d, cq: %d, ext2: %d, ti: %d, tci: %d",
89
- le64_to_cpu(descr->addr), descr->len, descr->gen, descr->rsvd,
90
+ descr->addr, descr->len, descr->gen, descr->rsvd,
91
descr->dtype, descr->ext1, descr->msscof, descr->hlen, descr->om,
92
descr->eop, descr->cq, descr->ext2, descr->ti, descr->tci);
93
}
94
@@ -XXX,XX +XXX,XX @@ vmxnet3_dump_rx_descr(struct Vmxnet3_RxDesc *descr)
95
{
96
VMW_PKPRN("RX DESCR: addr %" PRIx64 ", len: %d, gen: %d, rsvd: %d, "
97
"dtype: %d, ext1: %d, btype: %d",
98
- le64_to_cpu(descr->addr), descr->len, descr->gen,
99
+ descr->addr, descr->len, descr->gen,
100
descr->rsvd, descr->dtype, descr->ext1, descr->btype);
101
}
102
103
@@ -XXX,XX +XXX,XX @@ static void vmxnet3_complete_packet(VMXNET3State *s, int qidx, uint32_t tx_ridx)
104
memset(&txcq_descr, 0, sizeof(txcq_descr));
105
txcq_descr.txdIdx = tx_ridx;
106
txcq_descr.gen = vmxnet3_ring_curr_gen(&s->txq_descr[qidx].comp_ring);
107
-
108
+ txcq_descr.val1 = cpu_to_le32(txcq_descr.val1);
109
+ txcq_descr.val2 = cpu_to_le32(txcq_descr.val2);
110
vmxnet3_ring_write_curr_cell(d, &s->txq_descr[qidx].comp_ring, &txcq_descr);
111
112
/* Flush changes in TX descriptor before changing the counter value */
113
@@ -XXX,XX +XXX,XX @@ vmxnet3_on_rx_done_update_stats(VMXNET3State *s,
114
}
115
}
116
117
+static inline void
118
+vmxnet3_ring_read_curr_txdesc(PCIDevice *pcidev, Vmxnet3Ring *ring,
119
+ struct Vmxnet3_TxDesc *txd)
120
+{
121
+ vmxnet3_ring_read_curr_cell(pcidev, ring, txd);
122
+ txd->addr = le64_to_cpu(txd->addr);
123
+ txd->val1 = le32_to_cpu(txd->val1);
124
+ txd->val2 = le32_to_cpu(txd->val2);
125
+}
126
+
127
static inline bool
128
vmxnet3_pop_next_tx_descr(VMXNET3State *s,
129
int qidx,
130
@@ -XXX,XX +XXX,XX @@ vmxnet3_pop_next_tx_descr(VMXNET3State *s,
131
Vmxnet3Ring *ring = &s->txq_descr[qidx].tx_ring;
132
PCIDevice *d = PCI_DEVICE(s);
133
134
- vmxnet3_ring_read_curr_cell(d, ring, txd);
135
+ vmxnet3_ring_read_curr_txdesc(d, ring, txd);
136
if (txd->gen == vmxnet3_ring_curr_gen(ring)) {
137
/* Only read after generation field verification */
138
smp_rmb();
139
/* Re-read to be sure we got the latest version */
140
- vmxnet3_ring_read_curr_cell(d, ring, txd);
141
+ vmxnet3_ring_read_curr_txdesc(d, ring, txd);
142
VMXNET3_RING_DUMP(VMW_RIPRN, "TX", qidx, ring);
143
*descr_idx = vmxnet3_ring_curr_cell_idx(ring);
144
vmxnet3_inc_tx_consumption_counter(s, qidx);
145
@@ -XXX,XX +XXX,XX @@ static void vmxnet3_process_tx_queue(VMXNET3State *s, int qidx)
146
147
if (!s->skip_current_tx_pkt) {
148
data_len = (txd.len > 0) ? txd.len : VMXNET3_MAX_TX_BUF_SIZE;
149
- data_pa = le64_to_cpu(txd.addr);
150
+ data_pa = txd.addr;
151
152
if (!net_tx_pkt_add_raw_fragment(s->tx_pkt,
153
data_pa,
154
@@ -XXX,XX +XXX,XX @@ vmxnet3_read_next_rx_descr(VMXNET3State *s, int qidx, int ridx,
155
Vmxnet3Ring *ring = &s->rxq_descr[qidx].rx_ring[ridx];
156
*didx = vmxnet3_ring_curr_cell_idx(ring);
157
vmxnet3_ring_read_curr_cell(d, ring, dbuf);
158
+ dbuf->addr = le64_to_cpu(dbuf->addr);
159
+ dbuf->val1 = le32_to_cpu(dbuf->val1);
160
+ dbuf->ext1 = le32_to_cpu(dbuf->ext1);
161
}
162
163
static inline uint8_t
164
@@ -XXX,XX +XXX,XX @@ vmxnet3_pop_rxc_descr(VMXNET3State *s, int qidx, uint32_t *descr_gen)
165
166
pci_dma_read(PCI_DEVICE(s),
167
daddr, &rxcd, sizeof(struct Vmxnet3_RxCompDesc));
168
+ rxcd.val1 = le32_to_cpu(rxcd.val1);
169
+ rxcd.val2 = le32_to_cpu(rxcd.val2);
170
+ rxcd.val3 = le32_to_cpu(rxcd.val3);
171
ring_gen = vmxnet3_ring_curr_gen(&s->rxq_descr[qidx].comp_ring);
172
173
if (rxcd.gen != ring_gen) {
174
@@ -XXX,XX +XXX,XX @@ vmxnet3_pci_dma_writev(PCIDevice *pci_dev,
175
}
176
}
177
178
+static void
179
+vmxnet3_pci_dma_write_rxcd(PCIDevice *pcidev, dma_addr_t pa,
180
+ struct Vmxnet3_RxCompDesc *rxcd)
181
+{
182
+ rxcd->val1 = cpu_to_le32(rxcd->val1);
183
+ rxcd->val2 = cpu_to_le32(rxcd->val2);
184
+ rxcd->val3 = cpu_to_le32(rxcd->val3);
185
+ pci_dma_write(pcidev, pa, rxcd, sizeof(*rxcd));
186
+}
187
+
188
static bool
189
vmxnet3_indicate_packet(VMXNET3State *s)
190
{
191
@@ -XXX,XX +XXX,XX @@ vmxnet3_indicate_packet(VMXNET3State *s)
192
}
161
}
193
162
194
chunk_size = MIN(bytes_left, rxd.len);
163
if (net->has_vlan && !vlan_warned) {
195
- vmxnet3_pci_dma_writev(d, data, bytes_copied,
164
diff --git a/qapi/net.json b/qapi/net.json
196
- le64_to_cpu(rxd.addr), chunk_size);
165
index XXXXXXX..XXXXXXX 100644
197
+ vmxnet3_pci_dma_writev(d, data, bytes_copied, rxd.addr, chunk_size);
166
--- a/qapi/net.json
198
bytes_copied += chunk_size;
167
+++ b/qapi/net.json
199
bytes_left -= chunk_size;
168
@@ -XXX,XX +XXX,XX @@
200
169
# Connect two or more net clients through a software hub.
201
vmxnet3_dump_rx_descr(&rxd);
170
#
202
171
# @hubid: hub identifier number
203
if (ready_rxcd_pa != 0) {
172
+# @netdev: used to connect hub to a netdev instead of a device (since 2.12)
204
- pci_dma_write(d, ready_rxcd_pa, &rxcd, sizeof(rxcd));
173
#
205
+ vmxnet3_pci_dma_write_rxcd(d, ready_rxcd_pa, &rxcd);
174
# Since: 1.2
206
}
175
##
207
176
{ 'struct': 'NetdevHubPortOptions',
208
memset(&rxcd, 0, sizeof(struct Vmxnet3_RxCompDesc));
177
'data': {
209
@@ -XXX,XX +XXX,XX @@ vmxnet3_indicate_packet(VMXNET3State *s)
178
- 'hubid': 'int32' } }
210
rxcd.eop = 1;
179
+ 'hubid': 'int32',
211
rxcd.err = (bytes_left != 0);
180
+ '*netdev': 'str' } }
212
181
213
- pci_dma_write(d, ready_rxcd_pa, &rxcd, sizeof(rxcd));
182
##
214
+ vmxnet3_pci_dma_write_rxcd(d, ready_rxcd_pa, &rxcd);
183
# @NetdevNetmapOptions:
215
184
diff --git a/qemu-options.hx b/qemu-options.hx
216
/* Flush RX descriptor changes */
185
index XXXXXXX..XXXXXXX 100644
217
smp_wmb();
186
--- a/qemu-options.hx
218
diff --git a/hw/net/vmxnet3.h b/hw/net/vmxnet3.h
187
+++ b/qemu-options.hx
219
index XXXXXXX..XXXXXXX 100644
188
@@ -XXX,XX +XXX,XX @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
220
--- a/hw/net/vmxnet3.h
221
+++ b/hw/net/vmxnet3.h
222
@@ -XXX,XX +XXX,XX @@ enum {
223
struct Vmxnet3_TxDesc {
224
__le64 addr;
225
226
+ union {
227
+ struct {
228
#ifdef __BIG_ENDIAN_BITFIELD
229
- u32 msscof:14; /* MSS, checksum offset, flags */
230
- u32 ext1:1;
231
- u32 dtype:1; /* descriptor type */
232
- u32 rsvd:1;
233
- u32 gen:1; /* generation bit */
234
- u32 len:14;
235
+ u32 msscof:14; /* MSS, checksum offset, flags */
236
+ u32 ext1:1;
237
+ u32 dtype:1; /* descriptor type */
238
+ u32 rsvd:1;
239
+ u32 gen:1; /* generation bit */
240
+ u32 len:14;
241
#else
242
- u32 len:14;
243
- u32 gen:1; /* generation bit */
244
- u32 rsvd:1;
245
- u32 dtype:1; /* descriptor type */
246
- u32 ext1:1;
247
- u32 msscof:14; /* MSS, checksum offset, flags */
248
+ u32 len:14;
249
+ u32 gen:1; /* generation bit */
250
+ u32 rsvd:1;
251
+ u32 dtype:1; /* descriptor type */
252
+ u32 ext1:1;
253
+ u32 msscof:14; /* MSS, checksum offset, flags */
254
#endif /* __BIG_ENDIAN_BITFIELD */
255
-
256
+ };
257
+ u32 val1;
258
+ };
259
+
260
+ union {
261
+ struct {
262
#ifdef __BIG_ENDIAN_BITFIELD
263
- u32 tci:16; /* Tag to Insert */
264
- u32 ti:1; /* VLAN Tag Insertion */
265
- u32 ext2:1;
266
- u32 cq:1; /* completion request */
267
- u32 eop:1; /* End Of Packet */
268
- u32 om:2; /* offload mode */
269
- u32 hlen:10; /* header len */
270
+ u32 tci:16; /* Tag to Insert */
271
+ u32 ti:1; /* VLAN Tag Insertion */
272
+ u32 ext2:1;
273
+ u32 cq:1; /* completion request */
274
+ u32 eop:1; /* End Of Packet */
275
+ u32 om:2; /* offload mode */
276
+ u32 hlen:10; /* header len */
277
#else
278
- u32 hlen:10; /* header len */
279
- u32 om:2; /* offload mode */
280
- u32 eop:1; /* End Of Packet */
281
- u32 cq:1; /* completion request */
282
- u32 ext2:1;
283
- u32 ti:1; /* VLAN Tag Insertion */
284
- u32 tci:16; /* Tag to Insert */
285
+ u32 hlen:10; /* header len */
286
+ u32 om:2; /* offload mode */
287
+ u32 eop:1; /* End Of Packet */
288
+ u32 cq:1; /* completion request */
289
+ u32 ext2:1;
290
+ u32 ti:1; /* VLAN Tag Insertion */
291
+ u32 tci:16; /* Tag to Insert */
292
#endif /* __BIG_ENDIAN_BITFIELD */
293
+ };
294
+ u32 val2;
295
+ };
296
};
297
298
/* TxDesc.OM values */
299
@@ -XXX,XX +XXX,XX @@ struct Vmxnet3_TxDataDesc {
300
#define VMXNET3_TCD_GEN_DWORD_SHIFT 3
301
302
struct Vmxnet3_TxCompDesc {
303
- u32 txdIdx:12; /* Index of the EOP TxDesc */
304
- u32 ext1:20;
305
-
306
+ union {
307
+ struct {
308
+#ifdef __BIG_ENDIAN_BITFIELD
309
+ u32 ext1:20;
310
+ u32 txdIdx:12; /* Index of the EOP TxDesc */
311
+#else
312
+ u32 txdIdx:12; /* Index of the EOP TxDesc */
313
+ u32 ext1:20;
314
+#endif
315
+ };
316
+ u32 val1;
317
+ };
318
__le32 ext2;
319
__le32 ext3;
320
321
- u32 rsvd:24;
322
- u32 type:7; /* completion type */
323
- u32 gen:1; /* generation bit */
324
+ union {
325
+ struct {
326
+#ifdef __BIG_ENDIAN_BITFIELD
327
+ u32 gen:1; /* generation bit */
328
+ u32 type:7; /* completion type */
329
+ u32 rsvd:24;
330
+#else
331
+ u32 rsvd:24;
332
+ u32 type:7; /* completion type */
333
+ u32 gen:1; /* generation bit */
334
+#endif
335
+ };
336
+ u32 val2;
337
+ };
338
};
339
340
struct Vmxnet3_RxDesc {
341
__le64 addr;
342
-
343
+ union {
344
+ struct {
345
#ifdef __BIG_ENDIAN_BITFIELD
346
- u32 gen:1; /* Generation bit */
347
- u32 rsvd:15;
348
- u32 dtype:1; /* Descriptor type */
349
- u32 btype:1; /* Buffer Type */
350
- u32 len:14;
351
+ u32 gen:1; /* Generation bit */
352
+ u32 rsvd:15;
353
+ u32 dtype:1; /* Descriptor type */
354
+ u32 btype:1; /* Buffer Type */
355
+ u32 len:14;
356
#else
357
- u32 len:14;
358
- u32 btype:1; /* Buffer Type */
359
- u32 dtype:1; /* Descriptor type */
360
- u32 rsvd:15;
361
- u32 gen:1; /* Generation bit */
362
+ u32 len:14;
363
+ u32 btype:1; /* Buffer Type */
364
+ u32 dtype:1; /* Descriptor type */
365
+ u32 rsvd:15;
366
+ u32 gen:1; /* Generation bit */
367
#endif
189
#endif
368
+ };
190
"-netdev vhost-user,id=str,chardev=dev[,vhostforce=on|off]\n"
369
+ u32 val1;
191
" configure a vhost-user network, backed by a chardev 'dev'\n"
370
+ };
192
- "-netdev hubport,id=str,hubid=n\n"
371
u32 ext1;
193
+ "-netdev hubport,id=str,hubid=n[,netdev=nd]\n"
372
};
194
" configure a hub port on QEMU VLAN 'n'\n", QEMU_ARCH_ALL)
373
195
DEF("net", HAS_ARG, QEMU_OPTION_net,
374
@@ -XXX,XX +XXX,XX @@ struct Vmxnet3_RxDesc {
196
"-net nic[,vlan=n][,netdev=nd][,macaddr=mac][,model=type][,name=str][,addr=str][,vectors=v]\n"
375
#define VMXNET3_RXD_GEN_SHIFT 31
197
@@ -XXX,XX +XXX,XX @@ vde_switch -F -sock /tmp/myswitch
376
198
qemu-system-i386 linux.img -net nic -net vde,sock=/tmp/myswitch
377
struct Vmxnet3_RxCompDesc {
199
@end example
378
+ union {
200
379
+ struct {
201
-@item -netdev hubport,id=@var{id},hubid=@var{hubid}
380
#ifdef __BIG_ENDIAN_BITFIELD
202
+@item -netdev hubport,id=@var{id},hubid=@var{hubid}[,netdev=@var{nd}]
381
- u32 ext2:1;
203
382
- u32 cnc:1; /* Checksum Not Calculated */
204
Create a hub port on QEMU "vlan" @var{hubid}.
383
- u32 rssType:4; /* RSS hash type used */
205
384
- u32 rqID:10; /* rx queue/ring ID */
206
The hubport netdev lets you connect a NIC to a QEMU "vlan" instead of a single
385
- u32 sop:1; /* Start of Packet */
207
netdev. @code{-net} and @code{-device} with parameter @option{vlan} create the
386
- u32 eop:1; /* End of Packet */
208
-required hub automatically.
387
- u32 ext1:2;
209
+required hub automatically. Alternatively, you can also connect the hubport
388
- u32 rxdIdx:12; /* Index of the RxDesc */
210
+to another netdev with ID @var{nd} by using the @option{netdev=@var{nd}}
389
+ u32 ext2:1;
211
+option.
390
+ u32 cnc:1; /* Checksum Not Calculated */
212
391
+ u32 rssType:4; /* RSS hash type used */
213
@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off][,queues=n]
392
+ u32 rqID:10; /* rx queue/ring ID */
214
393
+ u32 sop:1; /* Start of Packet */
394
+ u32 eop:1; /* End of Packet */
395
+ u32 ext1:2;
396
+ u32 rxdIdx:12; /* Index of the RxDesc */
397
#else
398
- u32 rxdIdx:12; /* Index of the RxDesc */
399
- u32 ext1:2;
400
- u32 eop:1; /* End of Packet */
401
- u32 sop:1; /* Start of Packet */
402
- u32 rqID:10; /* rx queue/ring ID */
403
- u32 rssType:4; /* RSS hash type used */
404
- u32 cnc:1; /* Checksum Not Calculated */
405
- u32 ext2:1;
406
+ u32 rxdIdx:12; /* Index of the RxDesc */
407
+ u32 ext1:2;
408
+ u32 eop:1; /* End of Packet */
409
+ u32 sop:1; /* Start of Packet */
410
+ u32 rqID:10; /* rx queue/ring ID */
411
+ u32 rssType:4; /* RSS hash type used */
412
+ u32 cnc:1; /* Checksum Not Calculated */
413
+ u32 ext2:1;
414
#endif /* __BIG_ENDIAN_BITFIELD */
415
+ };
416
+ u32 val1;
417
+ };
418
419
__le32 rssHash; /* RSS hash value */
420
421
+ union {
422
+ struct {
423
#ifdef __BIG_ENDIAN_BITFIELD
424
- u32 tci:16; /* Tag stripped */
425
- u32 ts:1; /* Tag is stripped */
426
- u32 err:1; /* Error */
427
- u32 len:14; /* data length */
428
+ u32 tci:16; /* Tag stripped */
429
+ u32 ts:1; /* Tag is stripped */
430
+ u32 err:1; /* Error */
431
+ u32 len:14; /* data length */
432
#else
433
- u32 len:14; /* data length */
434
- u32 err:1; /* Error */
435
- u32 ts:1; /* Tag is stripped */
436
- u32 tci:16; /* Tag stripped */
437
+ u32 len:14; /* data length */
438
+ u32 err:1; /* Error */
439
+ u32 ts:1; /* Tag is stripped */
440
+ u32 tci:16; /* Tag stripped */
441
#endif /* __BIG_ENDIAN_BITFIELD */
442
+ };
443
+ u32 val2;
444
+ };
445
446
-
447
+ union {
448
+ struct {
449
#ifdef __BIG_ENDIAN_BITFIELD
450
- u32 gen:1; /* generation bit */
451
- u32 type:7; /* completion type */
452
- u32 fcs:1; /* Frame CRC correct */
453
- u32 frg:1; /* IP Fragment */
454
- u32 v4:1; /* IPv4 */
455
- u32 v6:1; /* IPv6 */
456
- u32 ipc:1; /* IP Checksum Correct */
457
- u32 tcp:1; /* TCP packet */
458
- u32 udp:1; /* UDP packet */
459
- u32 tuc:1; /* TCP/UDP Checksum Correct */
460
- u32 csum:16;
461
+ u32 gen:1; /* generation bit */
462
+ u32 type:7; /* completion type */
463
+ u32 fcs:1; /* Frame CRC correct */
464
+ u32 frg:1; /* IP Fragment */
465
+ u32 v4:1; /* IPv4 */
466
+ u32 v6:1; /* IPv6 */
467
+ u32 ipc:1; /* IP Checksum Correct */
468
+ u32 tcp:1; /* TCP packet */
469
+ u32 udp:1; /* UDP packet */
470
+ u32 tuc:1; /* TCP/UDP Checksum Correct */
471
+ u32 csum:16;
472
#else
473
- u32 csum:16;
474
- u32 tuc:1; /* TCP/UDP Checksum Correct */
475
- u32 udp:1; /* UDP packet */
476
- u32 tcp:1; /* TCP packet */
477
- u32 ipc:1; /* IP Checksum Correct */
478
- u32 v6:1; /* IPv6 */
479
- u32 v4:1; /* IPv4 */
480
- u32 frg:1; /* IP Fragment */
481
- u32 fcs:1; /* Frame CRC correct */
482
- u32 type:7; /* completion type */
483
- u32 gen:1; /* generation bit */
484
+ u32 csum:16;
485
+ u32 tuc:1; /* TCP/UDP Checksum Correct */
486
+ u32 udp:1; /* UDP packet */
487
+ u32 tcp:1; /* TCP packet */
488
+ u32 ipc:1; /* IP Checksum Correct */
489
+ u32 v6:1; /* IPv6 */
490
+ u32 v4:1; /* IPv4 */
491
+ u32 frg:1; /* IP Fragment */
492
+ u32 fcs:1; /* Frame CRC correct */
493
+ u32 type:7; /* completion type */
494
+ u32 gen:1; /* generation bit */
495
#endif /* __BIG_ENDIAN_BITFIELD */
496
+ };
497
+ u32 val3;
498
+ };
499
};
500
501
/* fields in RxCompDesc we access via Vmxnet3_GenericDesc.dword[3] */
502
--
215
--
503
2.7.4
216
2.7.4
504
217
505
218
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
Since commit 1865e288a823c764cd4344d ("Fix eepro100 simple transmission
3
It does not make much sense to limit these commands to the legacy 'vlan'
4
mode"), the test/pxe-test is broken for the eepro100 device on big
4
concept only, they should work with the modern netdevs, too. So now
5
endian hosts. However, it seems like that commit did not introduce the
5
it is possible to use this command with one, two or three parameters.
6
problem, but just uncovered it: The EEPRO100State->tx.tbd_array_addr and
6
7
EEPRO100State->tx.tcb_bytes fields are already in host byte order, since
7
With one parameter, the command installs a hostfwd rule on the default
8
they have already been byte-swapped in the read_cb() function.
8
"user" network:
9
Thus byte-swapping them in tx_command() again results in the wrong
9
hostfwd_add tcp:...
10
endianness. Removing the byte-swapping here fixes the pxe-test.
10
11
With two parameters, the command installs a hostfwd rule on a netdev
12
(that's the new way of using this command):
13
hostfwd_add netdev_id tcp:...
14
15
With three parameters, the command installs a rule on a 'vlan' (aka hub):
16
hostfwd_add hub_id name tcp:...
17
18
Same applies to the hostfwd_remove command now.
11
19
12
Signed-off-by: Thomas Huth <thuth@redhat.com>
20
Signed-off-by: Thomas Huth <thuth@redhat.com>
13
Signed-off-by: Jason Wang <jasowang@redhat.com>
21
Signed-off-by: Jason Wang <jasowang@redhat.com>
14
---
22
---
15
hw/net/eepro100.c | 4 ++--
23
hmp-commands.hx | 4 ++--
16
1 file changed, 2 insertions(+), 2 deletions(-)
24
net/slirp.c | 33 +++++++++++++++++++++++----------
25
2 files changed, 25 insertions(+), 12 deletions(-)
17
26
18
diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
27
diff --git a/hmp-commands.hx b/hmp-commands.hx
19
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/net/eepro100.c
29
--- a/hmp-commands.hx
21
+++ b/hw/net/eepro100.c
30
+++ b/hmp-commands.hx
22
@@ -XXX,XX +XXX,XX @@ static void read_cb(EEPRO100State *s)
31
@@ -XXX,XX +XXX,XX @@ ETEXI
23
32
{
24
static void tx_command(EEPRO100State *s)
33
.name = "hostfwd_add",
34
.args_type = "arg1:s,arg2:s?,arg3:s?",
35
- .params = "[vlan_id name] [tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport",
36
+ .params = "[hub_id name]|[netdev_id] [tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport",
37
.help = "redirect TCP or UDP connections from host to guest (requires -net user)",
38
.cmd = hmp_hostfwd_add,
39
},
40
@@ -XXX,XX +XXX,XX @@ ETEXI
41
{
42
.name = "hostfwd_remove",
43
.args_type = "arg1:s,arg2:s?,arg3:s?",
44
- .params = "[vlan_id name] [tcp|udp]:[hostaddr]:hostport",
45
+ .params = "[hub_id name]|[netdev_id] [tcp|udp]:[hostaddr]:hostport",
46
.help = "remove host-to-guest TCP or UDP redirection",
47
.cmd = hmp_hostfwd_remove,
48
},
49
diff --git a/net/slirp.c b/net/slirp.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/net/slirp.c
52
+++ b/net/slirp.c
53
@@ -XXX,XX +XXX,XX @@ error:
54
return -1;
55
}
56
57
-static SlirpState *slirp_lookup(Monitor *mon, const char *vlan,
58
- const char *stack)
59
+static SlirpState *slirp_lookup(Monitor *mon, const char *hub_id,
60
+ const char *name)
25
{
61
{
26
- uint32_t tbd_array = le32_to_cpu(s->tx.tbd_array_addr);
62
-
27
- uint16_t tcb_bytes = (le16_to_cpu(s->tx.tcb_bytes) & 0x3fff);
63
- if (vlan) {
28
+ uint32_t tbd_array = s->tx.tbd_array_addr;
64
+ if (name) {
29
+ uint16_t tcb_bytes = s->tx.tcb_bytes & 0x3fff;
65
NetClientState *nc;
30
/* Sends larger than MAX_ETH_FRAME_SIZE are allowed, up to 2600 bytes. */
66
- nc = net_hub_find_client_by_name(strtol(vlan, NULL, 0), stack);
31
uint8_t buf[2600];
67
- if (!nc) {
32
uint16_t size = 0;
68
- monitor_printf(mon, "unrecognized (vlan-id, stackname) pair\n");
69
- return NULL;
70
+ if (hub_id) {
71
+ nc = net_hub_find_client_by_name(strtol(hub_id, NULL, 0), name);
72
+ if (!nc) {
73
+ monitor_printf(mon, "unrecognized (vlan-id, stackname) pair\n");
74
+ return NULL;
75
+ }
76
+ } else {
77
+ nc = qemu_find_netdev(name);
78
+ if (!nc) {
79
+ monitor_printf(mon, "unrecognized netdev id '%s'\n", name);
80
+ return NULL;
81
+ }
82
}
83
if (strcmp(nc->model, "user")) {
84
monitor_printf(mon, "invalid device specified\n");
85
@@ -XXX,XX +XXX,XX @@ void hmp_hostfwd_remove(Monitor *mon, const QDict *qdict)
86
const char *arg2 = qdict_get_try_str(qdict, "arg2");
87
const char *arg3 = qdict_get_try_str(qdict, "arg3");
88
89
- if (arg2) {
90
+ if (arg3) {
91
s = slirp_lookup(mon, arg1, arg2);
92
src_str = arg3;
93
+ } else if (arg2) {
94
+ s = slirp_lookup(mon, NULL, arg1);
95
+ src_str = arg2;
96
} else {
97
s = slirp_lookup(mon, NULL, NULL);
98
src_str = arg1;
99
@@ -XXX,XX +XXX,XX @@ void hmp_hostfwd_add(Monitor *mon, const QDict *qdict)
100
const char *arg2 = qdict_get_try_str(qdict, "arg2");
101
const char *arg3 = qdict_get_try_str(qdict, "arg3");
102
103
- if (arg2) {
104
+ if (arg3) {
105
s = slirp_lookup(mon, arg1, arg2);
106
redir_str = arg3;
107
+ } else if (arg2) {
108
+ s = slirp_lookup(mon, NULL, arg1);
109
+ redir_str = arg2;
110
} else {
111
s = slirp_lookup(mon, NULL, NULL);
112
redir_str = arg1;
33
--
113
--
34
2.7.4
114
2.7.4
35
115
36
116
diff view generated by jsdifflib
1
This reverts commit 5e89dc01133f8f5e621f6b66b356c6f37d31dafb since:
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
- we should use ID in the spec instead the one used by OEM
3
The vlan concept is marked as deprecated, so we should not use
4
- in the future, we should allow changing id through either property
4
this for examples in the documentation anymore.
5
or EEPROM file.
6
5
7
Cc: Stefan Weil <sw@weilnetz.de>
6
Signed-off-by: Thomas Huth <thuth@redhat.com>
8
Cc: Michael Nawrocki <michael.nawrocki@gtri.gatech.edu>
9
Cc: Peter Maydell <peter.maydell@linaro.org>
10
Cc: Michael S. Tsirkin <mst@redhat.com>
11
Reviewed-by: Stefan Weil <sw@weilnetz.de>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
---
8
---
14
hw/net/eepro100.c | 13 -------------
9
qemu-options.hx | 4 ++--
15
include/hw/compat.h | 4 ----
10
1 file changed, 2 insertions(+), 2 deletions(-)
16
include/hw/pci/pci.h | 1 -
17
qemu-options.hx | 2 +-
18
4 files changed, 1 insertion(+), 19 deletions(-)
19
11
20
diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/net/eepro100.c
23
+++ b/hw/net/eepro100.c
24
@@ -XXX,XX +XXX,XX @@ typedef struct {
25
const char *name;
26
const char *desc;
27
uint16_t device_id;
28
- uint16_t alt_device_id;
29
uint8_t revision;
30
uint16_t subsystem_vendor_id;
31
uint16_t subsystem_id;
32
@@ -XXX,XX +XXX,XX @@ typedef struct {
33
/* Quasi static device properties (no need to save them). */
34
uint16_t stats_size;
35
bool has_extended_tcb_support;
36
- bool use_alt_device_id;
37
} EEPRO100State;
38
39
/* Word indices in EEPROM. */
40
@@ -XXX,XX +XXX,XX @@ static void e100_nic_realize(PCIDevice *pci_dev, Error **errp)
41
42
TRACE(OTHER, logout("\n"));
43
44
- /* By default, the i82559a adapter uses the legacy PCI ID (for the
45
- * i82557). This allows the PCI ID to be changed to the alternate
46
- * i82559 ID if needed.
47
- */
48
- if (s->use_alt_device_id && strcmp(info->name, "i82559a") == 0) {
49
- pci_config_set_device_id(s->dev.config, info->alt_device_id);
50
- }
51
-
52
s->device = info->device;
53
54
e100_pci_reset(s, &local_err);
55
@@ -XXX,XX +XXX,XX @@ static E100PCIDeviceInfo e100_devices[] = {
56
.desc = "Intel i82559A Ethernet",
57
.device = i82559A,
58
.device_id = PCI_DEVICE_ID_INTEL_82557,
59
- .alt_device_id = PCI_DEVICE_ID_INTEL_82559,
60
.revision = 0x06,
61
.stats_size = 80,
62
.has_extended_tcb_support = true,
63
@@ -XXX,XX +XXX,XX @@ static E100PCIDeviceInfo *eepro100_get_class(EEPRO100State *s)
64
65
static Property e100_properties[] = {
66
DEFINE_NIC_PROPERTIES(EEPRO100State, conf),
67
- DEFINE_PROP_BOOL("x-use-alt-device-id", EEPRO100State, use_alt_device_id,
68
- true),
69
DEFINE_PROP_END_OF_LIST(),
70
};
71
72
diff --git a/include/hw/compat.h b/include/hw/compat.h
73
index XXXXXXX..XXXXXXX 100644
74
--- a/include/hw/compat.h
75
+++ b/include/hw/compat.h
76
@@ -XXX,XX +XXX,XX @@
77
.driver = "virtio-tablet-device",\
78
.property = "wheel-axis",\
79
.value = "false",\
80
- },{\
81
- .driver = "i82559a",\
82
- .property = "x-use-alt-device-id",\
83
- .value = "false",\
84
},
85
86
#define HW_COMPAT_2_9 \
87
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
88
index XXXXXXX..XXXXXXX 100644
89
--- a/include/hw/pci/pci.h
90
+++ b/include/hw/pci/pci.h
91
@@ -XXX,XX +XXX,XX @@ extern bool pci_available;
92
/* Intel (0x8086) */
93
#define PCI_DEVICE_ID_INTEL_82551IT 0x1209
94
#define PCI_DEVICE_ID_INTEL_82557 0x1229
95
-#define PCI_DEVICE_ID_INTEL_82559 0x1030
96
#define PCI_DEVICE_ID_INTEL_82801IR 0x2922
97
98
/* Red Hat / Qumranet (for QEMU) -- see pci-ids.txt */
99
diff --git a/qemu-options.hx b/qemu-options.hx
12
diff --git a/qemu-options.hx b/qemu-options.hx
100
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
101
--- a/qemu-options.hx
14
--- a/qemu-options.hx
102
+++ b/qemu-options.hx
15
+++ b/qemu-options.hx
103
@@ -XXX,XX +XXX,XX @@ that the card should have; this option currently only affects virtio cards; set
16
@@ -XXX,XX +XXX,XX @@ qemu-system-i386 linux.img -net nic -net tap
104
@var{v} = 0 to disable MSI-X. If no @option{-net} option is specified, a single
17
#launch a QEMU instance with two NICs, each one connected
105
NIC is created. QEMU can emulate several different models of network card.
18
#to a TAP device
106
Valid values for @var{type} are
19
qemu-system-i386 linux.img \
107
-@code{virtio}, @code{i82551}, @code{i82557b}, @code{i82559a}, @code{i82559er},
20
- -net nic,vlan=0 -net tap,vlan=0,ifname=tap0 \
108
+@code{virtio}, @code{i82551}, @code{i82557b}, @code{i82559er},
21
- -net nic,vlan=1 -net tap,vlan=1,ifname=tap1
109
@code{ne2k_pci}, @code{ne2k_isa}, @code{pcnet}, @code{rtl8139},
22
+ -netdev tap,id=nd0,ifname=tap0 -device e1000,netdev=nd0 \
110
@code{e1000}, @code{smc91c111}, @code{lance} and @code{mcf_fec}.
23
+ -netdev tap,id=nd1,ifname=tap1 -device rtl8139,netdev=nd1
111
Not all devices are supported on all targets. Use @code{-net nic,model=help}
24
@end example
25
26
@example
112
--
27
--
113
2.7.4
28
2.7.4
114
29
115
30
diff view generated by jsdifflib
1
From: Stefan Weil <sw@weilnetz.de>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Signed-off-by: Stefan Weil <sw@weilnetz.de>
3
gently asked by his automatic reply :)
4
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Signed-off-by: Jason Wang <jasowang@redhat.com>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
5
---
7
---
6
MAINTAINERS | 5 +++++
8
MAINTAINERS | 8 ++++----
7
1 file changed, 5 insertions(+)
9
1 file changed, 4 insertions(+), 4 deletions(-)
8
10
9
diff --git a/MAINTAINERS b/MAINTAINERS
11
diff --git a/MAINTAINERS b/MAINTAINERS
10
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
11
--- a/MAINTAINERS
13
--- a/MAINTAINERS
12
+++ b/MAINTAINERS
14
+++ b/MAINTAINERS
13
@@ -XXX,XX +XXX,XX @@ M: Dmitry Fleytman <dmitry@daynix.com>
15
@@ -XXX,XX +XXX,XX @@ F: hw/scsi/mfi.h
16
F: tests/megasas-test.c
17
18
Network packet abstractions
19
-M: Dmitry Fleytman <dmitry@daynix.com>
20
+M: Dmitry Fleytman <dmitry.fleytman@gmail.com>
21
S: Maintained
22
F: include/net/eth.h
23
F: net/eth.c
24
@@ -XXX,XX +XXX,XX @@ F: hw/net/net_rx_pkt*
25
F: hw/net/net_tx_pkt*
26
27
Vmware
28
-M: Dmitry Fleytman <dmitry@daynix.com>
29
+M: Dmitry Fleytman <dmitry.fleytman@gmail.com>
30
S: Maintained
31
F: hw/net/vmxnet*
32
F: hw/scsi/vmw_pvscsi*
33
@@ -XXX,XX +XXX,XX @@ F: hw/mem/nvdimm.c
34
F: include/hw/mem/nvdimm.h
35
36
e1000x
37
-M: Dmitry Fleytman <dmitry@daynix.com>
38
+M: Dmitry Fleytman <dmitry.fleytman@gmail.com>
39
S: Maintained
40
F: hw/net/e1000x*
41
42
e1000e
43
-M: Dmitry Fleytman <dmitry@daynix.com>
44
+M: Dmitry Fleytman <dmitry.fleytman@gmail.com>
14
S: Maintained
45
S: Maintained
15
F: hw/net/e1000e*
46
F: hw/net/e1000e*
16
47
17
+eepro100
18
+M: Stefan Weil <sw@weilnetz.de>
19
+S: Maintained
20
+F: hw/net/eepro100.c
21
+
22
Generic Loader
23
M: Alistair Francis <alistair.francis@xilinx.com>
24
S: Maintained
25
--
48
--
26
2.7.4
49
2.7.4
27
50
28
51
diff view generated by jsdifflib