1
The following changes since commit e607bbee553cfe73072870cef458cfa4e78133e2:
1
The following changes since commit 3f429a3400822141651486193d6af625eeab05a5:
2
2
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)
3
Merge remote-tracking branch 'remotes/kraxel/tags/microvm-20200617-pull-request' into staging (2020-06-18 11:23:15 +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 bf4835a4d5338bb7424827715df22570a8adc67c:
9
for you to fetch changes up to 71830d8430e65dd20aec4765d87e60336148e1a6:
10
10
11
MAINTAINERS: update Dmitry Fleytman email (2018-01-29 16:05:38 +0800)
11
net: Drop the NetLegacy structure, always use Netdev instead (2020-06-18 21:05:52 +0800)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
14
15
Changes from V1:
16
- Fix build failure for virtio-net
17
15
----------------------------------------------------------------
18
----------------------------------------------------------------
16
Mao Zhongyi (2):
19
Derek Su (1):
17
colo: modified the payload compare function
20
colo-compare: Fix memory leak in packet_enqueue()
18
colo: compare the packet based on the tcp sequence number
19
21
20
Philippe Mathieu-Daudé (1):
22
Helge Deller (1):
21
MAINTAINERS: update Dmitry Fleytman email
23
Fix tulip breakage
22
24
23
Thomas Huth (3):
25
Jason Wang (1):
24
net: Allow hubports to connect to other netdevs
26
net: use peer when purging queue in qemu_flush_or_purge_queue_packets()
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
27
27
28
MAINTAINERS | 8 +-
28
Lukas Straub (6):
29
hmp-commands.hx | 4 +-
29
net/colo-compare.c: Create event_bh with the right AioContext
30
net/colo-compare.c | 411 +++++++++++++++++++++++++++++++++--------------------
30
chardev/char.c: Use qemu_co_sleep_ns if in coroutine
31
net/colo.c | 9 ++
31
net/colo-compare.c: Fix deadlock in compare_chr_send
32
net/colo.h | 15 ++
32
net/colo-compare.c: Only hexdump packets if tracing is enabled
33
net/hub.c | 27 +++-
33
net/colo-compare.c: Check that colo-compare is active
34
net/hub.h | 3 +-
34
net/colo-compare.c: Correct ordering in complete and finalize
35
net/net.c | 2 +-
35
36
net/slirp.c | 33 +++--
36
Philippe Mathieu-Daudé (3):
37
net/trace-events | 2 +-
37
hw/net/tulip: Fix 'Descriptor Error' definition
38
qapi/net.json | 4 +-
38
hw/net/tulip: Log descriptor overflows
39
qemu-options.hx | 12 +-
39
hw/net/e1000e: Do not abort() on invalid PSRCTL register value
40
12 files changed, 347 insertions(+), 183 deletions(-)
40
41
Sai Pavan Boddu (11):
42
net: cadence_gem: Fix debug statements
43
net: cadence_gem: Fix the queue address update during wrap around
44
net: cadence_gem: Fix irq update w.r.t queue
45
net: cadence_gem: Define access permission for interrupt registers
46
net: cadence_gem: Set ISR according to queue in use
47
net: cadence_gem: Move tx/rx packet buffert to CadenceGEMState
48
net: cadence_gem: Fix up code style
49
net: cadence_gem: Add support for jumbo frames
50
net: cadnece_gem: Update irq_read_clear field of designcfg_debug1 reg
51
net: cadence_gem: Update the reset value for interrupt mask register
52
net: cadence_gem: TX_LAST bit should be set by guest
53
54
Thomas Huth (2):
55
net: Drop the legacy "name" parameter from the -net option
56
net: Drop the NetLegacy structure, always use Netdev instead
57
58
Tong Ho (1):
59
net: cadence_gem: Fix RX address filtering
60
61
Yuri Benditovich (7):
62
virtio-net: implement RSS configuration command
63
virtio-net: implement RX RSS processing
64
tap: allow extended virtio header with hash info
65
virtio-net: reference implementation of hash report
66
vmstate.h: provide VMSTATE_VARRAY_UINT16_ALLOC macro
67
virtio-net: add migration support for RSS and hash report
68
virtio-net: align RSC fields with updated virtio-net header
69
70
chardev/char.c | 7 +-
71
docs/system/deprecated.rst | 15 +-
72
hw/net/Makefile.objs | 1 +
73
hw/net/cadence_gem.c | 458 +++++++++++++++++++++++------------------
74
hw/net/e1000e_core.c | 10 +-
75
hw/net/trace-events | 3 +
76
hw/net/tulip.c | 12 +-
77
hw/net/tulip.h | 2 +-
78
hw/net/virtio-net.c | 387 ++++++++++++++++++++++++++++++----
79
include/hw/net/cadence_gem.h | 6 +
80
include/hw/virtio/virtio-net.h | 16 ++
81
include/migration/vmstate.h | 10 +
82
net/colo-compare.c | 277 ++++++++++++++++++-------
83
net/colo.c | 7 +
84
net/colo.h | 1 +
85
net/net.c | 89 ++------
86
net/tap.c | 3 +-
87
net/trace-events | 1 +
88
qapi/net.json | 49 -----
89
19 files changed, 905 insertions(+), 449 deletions(-)
41
90
42
91
diff view generated by jsdifflib
New patch
1
1
From: Yuri Benditovich <yuri.benditovich@daynix.com>
2
3
Optionally report RSS feature.
4
Handle RSS configuration command and keep RSS parameters
5
in virtio-net device context.
6
7
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
10
hw/net/trace-events | 3 +
11
hw/net/virtio-net.c | 167 ++++++++++++++++++++++++++++++++++++++---
12
include/hw/virtio/virtio-net.h | 13 ++++
13
3 files changed, 174 insertions(+), 9 deletions(-)
14
15
diff --git a/hw/net/trace-events b/hw/net/trace-events
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/net/trace-events
18
+++ b/hw/net/trace-events
19
@@ -XXX,XX +XXX,XX @@ virtio_net_announce_notify(void) ""
20
virtio_net_announce_timer(int round) "%d"
21
virtio_net_handle_announce(int round) "%d"
22
virtio_net_post_load_device(void)
23
+virtio_net_rss_disable(void)
24
+virtio_net_rss_error(const char *msg, uint32_t value) "%s, value 0x%08x"
25
+virtio_net_rss_enable(uint32_t p1, uint16_t p2, uint8_t p3) "hashes 0x%x, table of %d, key of %d"
26
27
# tulip.c
28
tulip_reg_write(uint64_t addr, const char *name, int size, uint64_t val) "addr 0x%02"PRIx64" (%s) size %d value 0x%08"PRIx64
29
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/net/virtio-net.c
32
+++ b/hw/net/virtio-net.c
33
@@ -XXX,XX +XXX,XX @@
34
tso/gso/gro 'off'. */
35
#define VIRTIO_NET_RSC_DEFAULT_INTERVAL 300000
36
37
+#define VIRTIO_NET_RSS_SUPPORTED_HASHES (VIRTIO_NET_RSS_HASH_TYPE_IPv4 | \
38
+ VIRTIO_NET_RSS_HASH_TYPE_TCPv4 | \
39
+ VIRTIO_NET_RSS_HASH_TYPE_UDPv4 | \
40
+ VIRTIO_NET_RSS_HASH_TYPE_IPv6 | \
41
+ VIRTIO_NET_RSS_HASH_TYPE_TCPv6 | \
42
+ VIRTIO_NET_RSS_HASH_TYPE_UDPv6 | \
43
+ VIRTIO_NET_RSS_HASH_TYPE_IP_EX | \
44
+ VIRTIO_NET_RSS_HASH_TYPE_TCP_EX | \
45
+ VIRTIO_NET_RSS_HASH_TYPE_UDP_EX)
46
+
47
/* temporary until standard header include it */
48
#if !defined(VIRTIO_NET_HDR_F_RSC_INFO)
49
50
@@ -XXX,XX +XXX,XX @@ static VirtIOFeature feature_sizes[] = {
51
.end = endof(struct virtio_net_config, mtu)},
52
{.flags = 1ULL << VIRTIO_NET_F_SPEED_DUPLEX,
53
.end = endof(struct virtio_net_config, duplex)},
54
+ {.flags = 1ULL << VIRTIO_NET_F_RSS,
55
+ .end = endof(struct virtio_net_config, supported_hash_types)},
56
{}
57
};
58
59
@@ -XXX,XX +XXX,XX @@ static void virtio_net_get_config(VirtIODevice *vdev, uint8_t *config)
60
memcpy(netcfg.mac, n->mac, ETH_ALEN);
61
virtio_stl_p(vdev, &netcfg.speed, n->net_conf.speed);
62
netcfg.duplex = n->net_conf.duplex;
63
+ netcfg.rss_max_key_size = VIRTIO_NET_RSS_MAX_KEY_SIZE;
64
+ virtio_stw_p(vdev, &netcfg.rss_max_indirection_table_length,
65
+ VIRTIO_NET_RSS_MAX_TABLE_LEN);
66
+ virtio_stl_p(vdev, &netcfg.supported_hash_types,
67
+ VIRTIO_NET_RSS_SUPPORTED_HASHES);
68
memcpy(config, &netcfg, n->config_size);
69
}
70
71
@@ -XXX,XX +XXX,XX @@ static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features,
72
return features;
73
}
74
75
+ virtio_clear_feature(&features, VIRTIO_NET_F_RSS);
76
features = vhost_net_get_features(get_vhost_net(nc->peer), features);
77
vdev->backend_features = features;
78
79
@@ -XXX,XX +XXX,XX @@ static void virtio_net_set_features(VirtIODevice *vdev, uint64_t features)
80
}
81
82
virtio_net_set_multiqueue(n,
83
+ virtio_has_feature(features, VIRTIO_NET_F_RSS) ||
84
virtio_has_feature(features, VIRTIO_NET_F_MQ));
85
86
virtio_net_set_mrg_rx_bufs(n,
87
@@ -XXX,XX +XXX,XX @@ static int virtio_net_handle_announce(VirtIONet *n, uint8_t cmd,
88
}
89
}
90
91
+static void virtio_net_disable_rss(VirtIONet *n)
92
+{
93
+ if (n->rss_data.enabled) {
94
+ trace_virtio_net_rss_disable();
95
+ }
96
+ n->rss_data.enabled = false;
97
+}
98
+
99
+static uint16_t virtio_net_handle_rss(VirtIONet *n,
100
+ struct iovec *iov, unsigned int iov_cnt)
101
+{
102
+ VirtIODevice *vdev = VIRTIO_DEVICE(n);
103
+ struct virtio_net_rss_config cfg;
104
+ size_t s, offset = 0, size_get;
105
+ uint16_t queues, i;
106
+ struct {
107
+ uint16_t us;
108
+ uint8_t b;
109
+ } QEMU_PACKED temp;
110
+ const char *err_msg = "";
111
+ uint32_t err_value = 0;
112
+
113
+ if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_RSS)) {
114
+ err_msg = "RSS is not negotiated";
115
+ goto error;
116
+ }
117
+ size_get = offsetof(struct virtio_net_rss_config, indirection_table);
118
+ s = iov_to_buf(iov, iov_cnt, offset, &cfg, size_get);
119
+ if (s != size_get) {
120
+ err_msg = "Short command buffer";
121
+ err_value = (uint32_t)s;
122
+ goto error;
123
+ }
124
+ n->rss_data.hash_types = virtio_ldl_p(vdev, &cfg.hash_types);
125
+ n->rss_data.indirections_len =
126
+ virtio_lduw_p(vdev, &cfg.indirection_table_mask);
127
+ n->rss_data.indirections_len++;
128
+ if (!is_power_of_2(n->rss_data.indirections_len)) {
129
+ err_msg = "Invalid size of indirection table";
130
+ err_value = n->rss_data.indirections_len;
131
+ goto error;
132
+ }
133
+ if (n->rss_data.indirections_len > VIRTIO_NET_RSS_MAX_TABLE_LEN) {
134
+ err_msg = "Too large indirection table";
135
+ err_value = n->rss_data.indirections_len;
136
+ goto error;
137
+ }
138
+ n->rss_data.default_queue =
139
+ virtio_lduw_p(vdev, &cfg.unclassified_queue);
140
+ if (n->rss_data.default_queue >= n->max_queues) {
141
+ err_msg = "Invalid default queue";
142
+ err_value = n->rss_data.default_queue;
143
+ goto error;
144
+ }
145
+ offset += size_get;
146
+ size_get = sizeof(uint16_t) * n->rss_data.indirections_len;
147
+ g_free(n->rss_data.indirections_table);
148
+ n->rss_data.indirections_table = g_malloc(size_get);
149
+ if (!n->rss_data.indirections_table) {
150
+ err_msg = "Can't allocate indirections table";
151
+ err_value = n->rss_data.indirections_len;
152
+ goto error;
153
+ }
154
+ s = iov_to_buf(iov, iov_cnt, offset,
155
+ n->rss_data.indirections_table, size_get);
156
+ if (s != size_get) {
157
+ err_msg = "Short indirection table buffer";
158
+ err_value = (uint32_t)s;
159
+ goto error;
160
+ }
161
+ for (i = 0; i < n->rss_data.indirections_len; ++i) {
162
+ uint16_t val = n->rss_data.indirections_table[i];
163
+ n->rss_data.indirections_table[i] = virtio_lduw_p(vdev, &val);
164
+ }
165
+ offset += size_get;
166
+ size_get = sizeof(temp);
167
+ s = iov_to_buf(iov, iov_cnt, offset, &temp, size_get);
168
+ if (s != size_get) {
169
+ err_msg = "Can't get queues";
170
+ err_value = (uint32_t)s;
171
+ goto error;
172
+ }
173
+ queues = virtio_lduw_p(vdev, &temp.us);
174
+ if (queues == 0 || queues > n->max_queues) {
175
+ err_msg = "Invalid number of queues";
176
+ err_value = queues;
177
+ goto error;
178
+ }
179
+ if (temp.b > VIRTIO_NET_RSS_MAX_KEY_SIZE) {
180
+ err_msg = "Invalid key size";
181
+ err_value = temp.b;
182
+ goto error;
183
+ }
184
+ if (!temp.b && n->rss_data.hash_types) {
185
+ err_msg = "No key provided";
186
+ err_value = 0;
187
+ goto error;
188
+ }
189
+ if (!temp.b && !n->rss_data.hash_types) {
190
+ virtio_net_disable_rss(n);
191
+ return queues;
192
+ }
193
+ offset += size_get;
194
+ size_get = temp.b;
195
+ s = iov_to_buf(iov, iov_cnt, offset, n->rss_data.key, size_get);
196
+ if (s != size_get) {
197
+ err_msg = "Can get key buffer";
198
+ err_value = (uint32_t)s;
199
+ goto error;
200
+ }
201
+ n->rss_data.enabled = true;
202
+ trace_virtio_net_rss_enable(n->rss_data.hash_types,
203
+ n->rss_data.indirections_len,
204
+ temp.b);
205
+ return queues;
206
+error:
207
+ trace_virtio_net_rss_error(err_msg, err_value);
208
+ virtio_net_disable_rss(n);
209
+ return 0;
210
+}
211
+
212
static int virtio_net_handle_mq(VirtIONet *n, uint8_t cmd,
213
struct iovec *iov, unsigned int iov_cnt)
214
{
215
VirtIODevice *vdev = VIRTIO_DEVICE(n);
216
- struct virtio_net_ctrl_mq mq;
217
- size_t s;
218
uint16_t queues;
219
220
- s = iov_to_buf(iov, iov_cnt, 0, &mq, sizeof(mq));
221
- if (s != sizeof(mq)) {
222
- return VIRTIO_NET_ERR;
223
- }
224
+ virtio_net_disable_rss(n);
225
+ if (cmd == VIRTIO_NET_CTRL_MQ_RSS_CONFIG) {
226
+ queues = virtio_net_handle_rss(n, iov, iov_cnt);
227
+ } else if (cmd == VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET) {
228
+ struct virtio_net_ctrl_mq mq;
229
+ size_t s;
230
+ if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_MQ)) {
231
+ return VIRTIO_NET_ERR;
232
+ }
233
+ s = iov_to_buf(iov, iov_cnt, 0, &mq, sizeof(mq));
234
+ if (s != sizeof(mq)) {
235
+ return VIRTIO_NET_ERR;
236
+ }
237
+ queues = virtio_lduw_p(vdev, &mq.virtqueue_pairs);
238
239
- if (cmd != VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET) {
240
+ } else {
241
return VIRTIO_NET_ERR;
242
}
243
244
- queues = virtio_lduw_p(vdev, &mq.virtqueue_pairs);
245
-
246
if (queues < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN ||
247
queues > VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX ||
248
queues > n->max_queues ||
249
@@ -XXX,XX +XXX,XX @@ static void virtio_net_device_unrealize(DeviceState *dev)
250
g_free(n->vqs);
251
qemu_del_nic(n->nic);
252
virtio_net_rsc_cleanup(n);
253
+ g_free(n->rss_data.indirections_table);
254
virtio_cleanup(vdev);
255
}
256
257
@@ -XXX,XX +XXX,XX @@ static Property virtio_net_properties[] = {
258
DEFINE_PROP_BIT64("ctrl_guest_offloads", VirtIONet, host_features,
259
VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, true),
260
DEFINE_PROP_BIT64("mq", VirtIONet, host_features, VIRTIO_NET_F_MQ, false),
261
+ DEFINE_PROP_BIT64("rss", VirtIONet, host_features,
262
+ VIRTIO_NET_F_RSS, false),
263
DEFINE_PROP_BIT64("guest_rsc_ext", VirtIONet, host_features,
264
VIRTIO_NET_F_RSC_EXT, false),
265
DEFINE_PROP_UINT32("rsc_interval", VirtIONet, rsc_timeout,
266
diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
267
index XXXXXXX..XXXXXXX 100644
268
--- a/include/hw/virtio/virtio-net.h
269
+++ b/include/hw/virtio/virtio-net.h
270
@@ -XXX,XX +XXX,XX @@ typedef struct VirtioNetRscChain {
271
/* Maximum packet size we can receive from tap device: header + 64k */
272
#define VIRTIO_NET_MAX_BUFSIZE (sizeof(struct virtio_net_hdr) + (64 * KiB))
273
274
+#define VIRTIO_NET_RSS_MAX_KEY_SIZE 40
275
+#define VIRTIO_NET_RSS_MAX_TABLE_LEN 128
276
+
277
+typedef struct VirtioNetRssData {
278
+ bool enabled;
279
+ uint32_t hash_types;
280
+ uint8_t key[VIRTIO_NET_RSS_MAX_KEY_SIZE];
281
+ uint16_t indirections_len;
282
+ uint16_t *indirections_table;
283
+ uint16_t default_queue;
284
+} VirtioNetRssData;
285
+
286
typedef struct VirtIONetQueue {
287
VirtQueue *rx_vq;
288
VirtQueue *tx_vq;
289
@@ -XXX,XX +XXX,XX @@ struct VirtIONet {
290
bool failover;
291
DeviceListener primary_listener;
292
Notifier migration_state;
293
+ VirtioNetRssData rss_data;
294
};
295
296
void virtio_net_set_netclient_name(VirtIONet *n, const char *name,
297
--
298
2.5.0
299
300
diff view generated by jsdifflib
New patch
1
From: Yuri Benditovich <yuri.benditovich@daynix.com>
1
2
3
If VIRTIO_NET_F_RSS negotiated and RSS is enabled, process
4
incoming packets, calculate packet's hash and place the
5
packet into respective RX virtqueue.
6
7
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
10
hw/net/Makefile.objs | 1 +
11
hw/net/virtio-net.c | 88 +++++++++++++++++++++++++++++++++++++++++-
12
include/hw/virtio/virtio-net.h | 1 +
13
3 files changed, 88 insertions(+), 2 deletions(-)
14
15
diff --git a/hw/net/Makefile.objs b/hw/net/Makefile.objs
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/net/Makefile.objs
18
+++ b/hw/net/Makefile.objs
19
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MILKYMIST) += milkymist-minimac2.o
20
obj-$(CONFIG_PSERIES) += spapr_llan.o
21
obj-$(CONFIG_XILINX_ETHLITE) += xilinx_ethlite.o
22
23
+common-obj-$(CONFIG_VIRTIO_NET) += net_rx_pkt.o
24
obj-$(CONFIG_VIRTIO_NET) += virtio-net.o
25
common-obj-$(call land,$(CONFIG_VIRTIO_NET),$(CONFIG_VHOST_NET)) += vhost_net.o
26
common-obj-$(call lnot,$(call land,$(CONFIG_VIRTIO_NET),$(CONFIG_VHOST_NET))) += vhost_net-stub.o
27
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/net/virtio-net.c
30
+++ b/hw/net/virtio-net.c
31
@@ -XXX,XX +XXX,XX @@
32
#include "trace.h"
33
#include "monitor/qdev.h"
34
#include "hw/pci/pci.h"
35
+#include "net_rx_pkt.h"
36
37
#define VIRTIO_NET_VM_VERSION 11
38
39
@@ -XXX,XX +XXX,XX @@ static int receive_filter(VirtIONet *n, const uint8_t *buf, int size)
40
return 0;
41
}
42
43
+static uint8_t virtio_net_get_hash_type(bool isip4,
44
+ bool isip6,
45
+ bool isudp,
46
+ bool istcp,
47
+ uint32_t types)
48
+{
49
+ if (isip4) {
50
+ if (istcp && (types & VIRTIO_NET_RSS_HASH_TYPE_TCPv4)) {
51
+ return NetPktRssIpV4Tcp;
52
+ }
53
+ if (isudp && (types & VIRTIO_NET_RSS_HASH_TYPE_UDPv4)) {
54
+ return NetPktRssIpV4Udp;
55
+ }
56
+ if (types & VIRTIO_NET_RSS_HASH_TYPE_IPv4) {
57
+ return NetPktRssIpV4;
58
+ }
59
+ } else if (isip6) {
60
+ uint32_t mask = VIRTIO_NET_RSS_HASH_TYPE_TCP_EX |
61
+ VIRTIO_NET_RSS_HASH_TYPE_TCPv6;
62
+
63
+ if (istcp && (types & mask)) {
64
+ return (types & VIRTIO_NET_RSS_HASH_TYPE_TCP_EX) ?
65
+ NetPktRssIpV6TcpEx : NetPktRssIpV6Tcp;
66
+ }
67
+ mask = VIRTIO_NET_RSS_HASH_TYPE_UDP_EX | VIRTIO_NET_RSS_HASH_TYPE_UDPv6;
68
+ if (isudp && (types & mask)) {
69
+ return (types & VIRTIO_NET_RSS_HASH_TYPE_UDP_EX) ?
70
+ NetPktRssIpV6UdpEx : NetPktRssIpV6Udp;
71
+ }
72
+ mask = VIRTIO_NET_RSS_HASH_TYPE_IP_EX | VIRTIO_NET_RSS_HASH_TYPE_IPv6;
73
+ if (types & mask) {
74
+ return (types & VIRTIO_NET_RSS_HASH_TYPE_IP_EX) ?
75
+ NetPktRssIpV6Ex : NetPktRssIpV6;
76
+ }
77
+ }
78
+ return 0xff;
79
+}
80
+
81
+static int virtio_net_process_rss(NetClientState *nc, const uint8_t *buf,
82
+ size_t size)
83
+{
84
+ VirtIONet *n = qemu_get_nic_opaque(nc);
85
+ unsigned int index = nc->queue_index, new_index;
86
+ struct NetRxPkt *pkt = n->rx_pkt;
87
+ uint8_t net_hash_type;
88
+ uint32_t hash;
89
+ bool isip4, isip6, isudp, istcp;
90
+
91
+ net_rx_pkt_set_protocols(pkt, buf + n->host_hdr_len,
92
+ size - n->host_hdr_len);
93
+ net_rx_pkt_get_protocols(pkt, &isip4, &isip6, &isudp, &istcp);
94
+ if (isip4 && (net_rx_pkt_get_ip4_info(pkt)->fragment)) {
95
+ istcp = isudp = false;
96
+ }
97
+ if (isip6 && (net_rx_pkt_get_ip6_info(pkt)->fragment)) {
98
+ istcp = isudp = false;
99
+ }
100
+ net_hash_type = virtio_net_get_hash_type(isip4, isip6, isudp, istcp,
101
+ n->rss_data.hash_types);
102
+ if (net_hash_type > NetPktRssIpV6UdpEx) {
103
+ return n->rss_data.default_queue;
104
+ }
105
+
106
+ hash = net_rx_pkt_calc_rss_hash(pkt, net_hash_type, n->rss_data.key);
107
+ new_index = hash & (n->rss_data.indirections_len - 1);
108
+ new_index = n->rss_data.indirections_table[new_index];
109
+ if (index == new_index) {
110
+ return -1;
111
+ }
112
+ return new_index;
113
+}
114
+
115
static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
116
- size_t size)
117
+ size_t size, bool no_rss)
118
{
119
VirtIONet *n = qemu_get_nic_opaque(nc);
120
VirtIONetQueue *q = virtio_net_get_subqueue(nc);
121
@@ -XXX,XX +XXX,XX @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
122
return -1;
123
}
124
125
+ if (!no_rss && n->rss_data.enabled) {
126
+ int index = virtio_net_process_rss(nc, buf, size);
127
+ if (index >= 0) {
128
+ NetClientState *nc2 = qemu_get_subqueue(n->nic, index);
129
+ return virtio_net_receive_rcu(nc2, buf, size, true);
130
+ }
131
+ }
132
+
133
/* hdr_len refers to the header we supply to the guest */
134
if (!virtio_net_has_buffers(q, size + n->guest_hdr_len - n->host_hdr_len)) {
135
return 0;
136
@@ -XXX,XX +XXX,XX @@ static ssize_t virtio_net_do_receive(NetClientState *nc, const uint8_t *buf,
137
{
138
RCU_READ_LOCK_GUARD();
139
140
- return virtio_net_receive_rcu(nc, buf, size);
141
+ return virtio_net_receive_rcu(nc, buf, size, false);
142
}
143
144
static void virtio_net_rsc_extract_unit4(VirtioNetRscChain *chain,
145
@@ -XXX,XX +XXX,XX @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
146
147
QTAILQ_INIT(&n->rsc_chains);
148
n->qdev = dev;
149
+
150
+ net_rx_pkt_init(&n->rx_pkt, false);
151
}
152
153
static void virtio_net_device_unrealize(DeviceState *dev)
154
@@ -XXX,XX +XXX,XX @@ static void virtio_net_device_unrealize(DeviceState *dev)
155
qemu_del_nic(n->nic);
156
virtio_net_rsc_cleanup(n);
157
g_free(n->rss_data.indirections_table);
158
+ net_rx_pkt_uninit(n->rx_pkt);
159
virtio_cleanup(vdev);
160
}
161
162
diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
163
index XXXXXXX..XXXXXXX 100644
164
--- a/include/hw/virtio/virtio-net.h
165
+++ b/include/hw/virtio/virtio-net.h
166
@@ -XXX,XX +XXX,XX @@ struct VirtIONet {
167
DeviceListener primary_listener;
168
Notifier migration_state;
169
VirtioNetRssData rss_data;
170
+ struct NetRxPkt *rx_pkt;
171
};
172
173
void virtio_net_set_netclient_name(VirtIONet *n, const char *name,
174
--
175
2.5.0
176
177
diff view generated by jsdifflib
New patch
1
From: Yuri Benditovich <yuri.benditovich@daynix.com>
1
2
3
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
4
Signed-off-by: Jason Wang <jasowang@redhat.com>
5
---
6
net/tap.c | 3 ++-
7
1 file changed, 2 insertions(+), 1 deletion(-)
8
9
diff --git a/net/tap.c b/net/tap.c
10
index XXXXXXX..XXXXXXX 100644
11
--- a/net/tap.c
12
+++ b/net/tap.c
13
@@ -XXX,XX +XXX,XX @@ static void tap_set_vnet_hdr_len(NetClientState *nc, int len)
14
15
assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
16
assert(len == sizeof(struct virtio_net_hdr_mrg_rxbuf) ||
17
- len == sizeof(struct virtio_net_hdr));
18
+ len == sizeof(struct virtio_net_hdr) ||
19
+ len == sizeof(struct virtio_net_hdr_v1_hash));
20
21
tap_fd_set_vnet_hdr_len(s->fd, len);
22
s->host_vnet_hdr_len = len;
23
--
24
2.5.0
25
26
diff view generated by jsdifflib
New patch
1
1
From: Yuri Benditovich <yuri.benditovich@daynix.com>
2
3
Suggest VIRTIO_NET_F_HASH_REPORT if specified in device
4
parameters.
5
If the VIRTIO_NET_F_HASH_REPORT is set,
6
the device extends configuration space. If the feature
7
is negotiated, the packet layout is extended to
8
accomodate the hash information. In this case deliver
9
packet's hash value and report type in virtio header
10
extension.
11
Use for configuration the same procedure as already
12
used for RSS. We add two fields in rss_data that
13
controls what the device does with the calculated hash
14
if rss_data.enabled is set. If field 'populate' is set
15
the hash is set in the packet, if field 'redirect' is
16
set the hash is used to decide the queue to place the
17
packet to.
18
19
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
20
Signed-off-by: Jason Wang <jasowang@redhat.com>
21
---
22
hw/net/virtio-net.c | 99 +++++++++++++++++++++++++++++++++---------
23
include/hw/virtio/virtio-net.h | 2 +
24
2 files changed, 81 insertions(+), 20 deletions(-)
25
26
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/net/virtio-net.c
29
+++ b/hw/net/virtio-net.c
30
@@ -XXX,XX +XXX,XX @@ static VirtIOFeature feature_sizes[] = {
31
.end = endof(struct virtio_net_config, mtu)},
32
{.flags = 1ULL << VIRTIO_NET_F_SPEED_DUPLEX,
33
.end = endof(struct virtio_net_config, duplex)},
34
- {.flags = 1ULL << VIRTIO_NET_F_RSS,
35
+ {.flags = (1ULL << VIRTIO_NET_F_RSS) | (1ULL << VIRTIO_NET_F_HASH_REPORT),
36
.end = endof(struct virtio_net_config, supported_hash_types)},
37
{}
38
};
39
@@ -XXX,XX +XXX,XX @@ static void virtio_net_get_config(VirtIODevice *vdev, uint8_t *config)
40
netcfg.duplex = n->net_conf.duplex;
41
netcfg.rss_max_key_size = VIRTIO_NET_RSS_MAX_KEY_SIZE;
42
virtio_stw_p(vdev, &netcfg.rss_max_indirection_table_length,
43
- VIRTIO_NET_RSS_MAX_TABLE_LEN);
44
+ virtio_host_has_feature(vdev, VIRTIO_NET_F_RSS) ?
45
+ VIRTIO_NET_RSS_MAX_TABLE_LEN : 1);
46
virtio_stl_p(vdev, &netcfg.supported_hash_types,
47
VIRTIO_NET_RSS_SUPPORTED_HASHES);
48
memcpy(config, &netcfg, n->config_size);
49
@@ -XXX,XX +XXX,XX @@ static int peer_has_ufo(VirtIONet *n)
50
}
51
52
static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs,
53
- int version_1)
54
+ int version_1, int hash_report)
55
{
56
int i;
57
NetClientState *nc;
58
@@ -XXX,XX +XXX,XX @@ static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs,
59
n->mergeable_rx_bufs = mergeable_rx_bufs;
60
61
if (version_1) {
62
- n->guest_hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf);
63
+ n->guest_hdr_len = hash_report ?
64
+ sizeof(struct virtio_net_hdr_v1_hash) :
65
+ sizeof(struct virtio_net_hdr_mrg_rxbuf);
66
+ n->rss_data.populate_hash = !!hash_report;
67
} else {
68
n->guest_hdr_len = n->mergeable_rx_bufs ?
69
sizeof(struct virtio_net_hdr_mrg_rxbuf) :
70
@@ -XXX,XX +XXX,XX @@ static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features,
71
virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_TSO4);
72
virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_TSO6);
73
virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_ECN);
74
+
75
+ virtio_clear_feature(&features, VIRTIO_NET_F_HASH_REPORT);
76
}
77
78
if (!peer_has_vnet_hdr(n) || !peer_has_ufo(n)) {
79
@@ -XXX,XX +XXX,XX @@ static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features,
80
}
81
82
virtio_clear_feature(&features, VIRTIO_NET_F_RSS);
83
+ virtio_clear_feature(&features, VIRTIO_NET_F_HASH_REPORT);
84
features = vhost_net_get_features(get_vhost_net(nc->peer), features);
85
vdev->backend_features = features;
86
87
@@ -XXX,XX +XXX,XX @@ static void virtio_net_set_features(VirtIODevice *vdev, uint64_t features)
88
virtio_has_feature(features,
89
VIRTIO_NET_F_MRG_RXBUF),
90
virtio_has_feature(features,
91
- VIRTIO_F_VERSION_1));
92
+ VIRTIO_F_VERSION_1),
93
+ virtio_has_feature(features,
94
+ VIRTIO_NET_F_HASH_REPORT));
95
96
n->rsc4_enabled = virtio_has_feature(features, VIRTIO_NET_F_RSC_EXT) &&
97
virtio_has_feature(features, VIRTIO_NET_F_GUEST_TSO4);
98
n->rsc6_enabled = virtio_has_feature(features, VIRTIO_NET_F_RSC_EXT) &&
99
virtio_has_feature(features, VIRTIO_NET_F_GUEST_TSO6);
100
+ n->rss_data.redirect = virtio_has_feature(features, VIRTIO_NET_F_RSS);
101
102
if (n->has_vnet_hdr) {
103
n->curr_guest_offloads =
104
@@ -XXX,XX +XXX,XX @@ static void virtio_net_disable_rss(VirtIONet *n)
105
}
106
107
static uint16_t virtio_net_handle_rss(VirtIONet *n,
108
- struct iovec *iov, unsigned int iov_cnt)
109
+ struct iovec *iov,
110
+ unsigned int iov_cnt,
111
+ bool do_rss)
112
{
113
VirtIODevice *vdev = VIRTIO_DEVICE(n);
114
struct virtio_net_rss_config cfg;
115
@@ -XXX,XX +XXX,XX @@ static uint16_t virtio_net_handle_rss(VirtIONet *n,
116
const char *err_msg = "";
117
uint32_t err_value = 0;
118
119
- if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_RSS)) {
120
+ if (do_rss && !virtio_vdev_has_feature(vdev, VIRTIO_NET_F_RSS)) {
121
err_msg = "RSS is not negotiated";
122
goto error;
123
}
124
+ if (!do_rss && !virtio_vdev_has_feature(vdev, VIRTIO_NET_F_HASH_REPORT)) {
125
+ err_msg = "Hash report is not negotiated";
126
+ goto error;
127
+ }
128
size_get = offsetof(struct virtio_net_rss_config, indirection_table);
129
s = iov_to_buf(iov, iov_cnt, offset, &cfg, size_get);
130
if (s != size_get) {
131
@@ -XXX,XX +XXX,XX @@ static uint16_t virtio_net_handle_rss(VirtIONet *n,
132
n->rss_data.indirections_len =
133
virtio_lduw_p(vdev, &cfg.indirection_table_mask);
134
n->rss_data.indirections_len++;
135
+ if (!do_rss) {
136
+ n->rss_data.indirections_len = 1;
137
+ }
138
if (!is_power_of_2(n->rss_data.indirections_len)) {
139
err_msg = "Invalid size of indirection table";
140
err_value = n->rss_data.indirections_len;
141
@@ -XXX,XX +XXX,XX @@ static uint16_t virtio_net_handle_rss(VirtIONet *n,
142
err_value = n->rss_data.indirections_len;
143
goto error;
144
}
145
- n->rss_data.default_queue =
146
- virtio_lduw_p(vdev, &cfg.unclassified_queue);
147
+ n->rss_data.default_queue = do_rss ?
148
+ virtio_lduw_p(vdev, &cfg.unclassified_queue) : 0;
149
if (n->rss_data.default_queue >= n->max_queues) {
150
err_msg = "Invalid default queue";
151
err_value = n->rss_data.default_queue;
152
@@ -XXX,XX +XXX,XX @@ static uint16_t virtio_net_handle_rss(VirtIONet *n,
153
err_value = (uint32_t)s;
154
goto error;
155
}
156
- queues = virtio_lduw_p(vdev, &temp.us);
157
+ queues = do_rss ? virtio_lduw_p(vdev, &temp.us) : n->curr_queues;
158
if (queues == 0 || queues > n->max_queues) {
159
err_msg = "Invalid number of queues";
160
err_value = queues;
161
@@ -XXX,XX +XXX,XX @@ static int virtio_net_handle_mq(VirtIONet *n, uint8_t cmd,
162
uint16_t queues;
163
164
virtio_net_disable_rss(n);
165
+ if (cmd == VIRTIO_NET_CTRL_MQ_HASH_CONFIG) {
166
+ queues = virtio_net_handle_rss(n, iov, iov_cnt, false);
167
+ return queues ? VIRTIO_NET_OK : VIRTIO_NET_ERR;
168
+ }
169
if (cmd == VIRTIO_NET_CTRL_MQ_RSS_CONFIG) {
170
- queues = virtio_net_handle_rss(n, iov, iov_cnt);
171
+ queues = virtio_net_handle_rss(n, iov, iov_cnt, true);
172
} else if (cmd == VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET) {
173
struct virtio_net_ctrl_mq mq;
174
size_t s;
175
@@ -XXX,XX +XXX,XX @@ static uint8_t virtio_net_get_hash_type(bool isip4,
176
return 0xff;
177
}
178
179
+static void virtio_set_packet_hash(const uint8_t *buf, uint8_t report,
180
+ uint32_t hash)
181
+{
182
+ struct virtio_net_hdr_v1_hash *hdr = (void *)buf;
183
+ hdr->hash_value = hash;
184
+ hdr->hash_report = report;
185
+}
186
+
187
static int virtio_net_process_rss(NetClientState *nc, const uint8_t *buf,
188
size_t size)
189
{
190
VirtIONet *n = qemu_get_nic_opaque(nc);
191
- unsigned int index = nc->queue_index, new_index;
192
+ unsigned int index = nc->queue_index, new_index = index;
193
struct NetRxPkt *pkt = n->rx_pkt;
194
uint8_t net_hash_type;
195
uint32_t hash;
196
bool isip4, isip6, isudp, istcp;
197
+ static const uint8_t reports[NetPktRssIpV6UdpEx + 1] = {
198
+ VIRTIO_NET_HASH_REPORT_IPv4,
199
+ VIRTIO_NET_HASH_REPORT_TCPv4,
200
+ VIRTIO_NET_HASH_REPORT_TCPv6,
201
+ VIRTIO_NET_HASH_REPORT_IPv6,
202
+ VIRTIO_NET_HASH_REPORT_IPv6_EX,
203
+ VIRTIO_NET_HASH_REPORT_TCPv6_EX,
204
+ VIRTIO_NET_HASH_REPORT_UDPv4,
205
+ VIRTIO_NET_HASH_REPORT_UDPv6,
206
+ VIRTIO_NET_HASH_REPORT_UDPv6_EX
207
+ };
208
209
net_rx_pkt_set_protocols(pkt, buf + n->host_hdr_len,
210
size - n->host_hdr_len);
211
@@ -XXX,XX +XXX,XX @@ static int virtio_net_process_rss(NetClientState *nc, const uint8_t *buf,
212
net_hash_type = virtio_net_get_hash_type(isip4, isip6, isudp, istcp,
213
n->rss_data.hash_types);
214
if (net_hash_type > NetPktRssIpV6UdpEx) {
215
- return n->rss_data.default_queue;
216
+ if (n->rss_data.populate_hash) {
217
+ virtio_set_packet_hash(buf, VIRTIO_NET_HASH_REPORT_NONE, 0);
218
+ }
219
+ return n->rss_data.redirect ? n->rss_data.default_queue : -1;
220
}
221
222
hash = net_rx_pkt_calc_rss_hash(pkt, net_hash_type, n->rss_data.key);
223
- new_index = hash & (n->rss_data.indirections_len - 1);
224
- new_index = n->rss_data.indirections_table[new_index];
225
- if (index == new_index) {
226
- return -1;
227
+
228
+ if (n->rss_data.populate_hash) {
229
+ virtio_set_packet_hash(buf, reports[net_hash_type], hash);
230
}
231
- return new_index;
232
+
233
+ if (n->rss_data.redirect) {
234
+ new_index = hash & (n->rss_data.indirections_len - 1);
235
+ new_index = n->rss_data.indirections_table[new_index];
236
+ }
237
+
238
+ return (index == new_index) ? -1 : new_index;
239
}
240
241
static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
242
@@ -XXX,XX +XXX,XX @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
243
}
244
245
receive_header(n, sg, elem->in_num, buf, size);
246
+ if (n->rss_data.populate_hash) {
247
+ offset = sizeof(mhdr);
248
+ iov_from_buf(sg, elem->in_num, offset,
249
+ buf + offset, n->host_hdr_len - sizeof(mhdr));
250
+ }
251
offset = n->host_hdr_len;
252
total += n->guest_hdr_len;
253
guest_offset = n->guest_hdr_len;
254
@@ -XXX,XX +XXX,XX @@ static int virtio_net_post_load_device(void *opaque, int version_id)
255
trace_virtio_net_post_load_device();
256
virtio_net_set_mrg_rx_bufs(n, n->mergeable_rx_bufs,
257
virtio_vdev_has_feature(vdev,
258
- VIRTIO_F_VERSION_1));
259
+ VIRTIO_F_VERSION_1),
260
+ virtio_vdev_has_feature(vdev,
261
+ VIRTIO_NET_F_HASH_REPORT));
262
263
/* MAC_TABLE_ENTRIES may be different from the saved image */
264
if (n->mac_table.in_use > MAC_TABLE_ENTRIES) {
265
@@ -XXX,XX +XXX,XX @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
266
267
n->vqs[0].tx_waiting = 0;
268
n->tx_burst = n->net_conf.txburst;
269
- virtio_net_set_mrg_rx_bufs(n, 0, 0);
270
+ virtio_net_set_mrg_rx_bufs(n, 0, 0, 0);
271
n->promisc = 1; /* for compatibility */
272
273
n->mac_table.macs = g_malloc0(MAC_TABLE_ENTRIES * ETH_ALEN);
274
@@ -XXX,XX +XXX,XX @@ static Property virtio_net_properties[] = {
275
DEFINE_PROP_BIT64("mq", VirtIONet, host_features, VIRTIO_NET_F_MQ, false),
276
DEFINE_PROP_BIT64("rss", VirtIONet, host_features,
277
VIRTIO_NET_F_RSS, false),
278
+ DEFINE_PROP_BIT64("hash", VirtIONet, host_features,
279
+ VIRTIO_NET_F_HASH_REPORT, false),
280
DEFINE_PROP_BIT64("guest_rsc_ext", VirtIONet, host_features,
281
VIRTIO_NET_F_RSC_EXT, false),
282
DEFINE_PROP_UINT32("rsc_interval", VirtIONet, rsc_timeout,
283
diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
284
index XXXXXXX..XXXXXXX 100644
285
--- a/include/hw/virtio/virtio-net.h
286
+++ b/include/hw/virtio/virtio-net.h
287
@@ -XXX,XX +XXX,XX @@ typedef struct VirtioNetRscChain {
288
289
typedef struct VirtioNetRssData {
290
bool enabled;
291
+ bool redirect;
292
+ bool populate_hash;
293
uint32_t hash_types;
294
uint8_t key[VIRTIO_NET_RSS_MAX_KEY_SIZE];
295
uint16_t indirections_len;
296
--
297
2.5.0
298
299
diff view generated by jsdifflib
New patch
1
From: Yuri Benditovich <yuri.benditovich@daynix.com>
1
2
3
Similar to VMSTATE_VARRAY_UINT32_ALLOC, but the size is
4
16-bit field.
5
6
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
7
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
10
include/migration/vmstate.h | 10 ++++++++++
11
1 file changed, 10 insertions(+)
12
13
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/migration/vmstate.h
16
+++ b/include/migration/vmstate.h
17
@@ -XXX,XX +XXX,XX @@ extern const VMStateInfo vmstate_info_qlist;
18
.offset = vmstate_offset_pointer(_state, _field, _type), \
19
}
20
21
+#define VMSTATE_VARRAY_UINT16_ALLOC(_field, _state, _field_num, _version, _info, _type) {\
22
+ .name = (stringify(_field)), \
23
+ .version_id = (_version), \
24
+ .num_offset = vmstate_offset_value(_state, _field_num, uint16_t),\
25
+ .info = &(_info), \
26
+ .size = sizeof(_type), \
27
+ .flags = VMS_VARRAY_UINT16 | VMS_POINTER | VMS_ALLOC, \
28
+ .offset = vmstate_offset_pointer(_state, _field, _type), \
29
+}
30
+
31
#define VMSTATE_VARRAY_UINT16_UNSAFE(_field, _state, _field_num, _version, _info, _type) {\
32
.name = (stringify(_field)), \
33
.version_id = (_version), \
34
--
35
2.5.0
36
37
diff view generated by jsdifflib
New patch
1
From: Yuri Benditovich <yuri.benditovich@daynix.com>
1
2
3
Save and restore RSS/hash report configuration.
4
5
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
---
8
hw/net/virtio-net.c | 37 +++++++++++++++++++++++++++++++++++++
9
1 file changed, 37 insertions(+)
10
11
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/net/virtio-net.c
14
+++ b/hw/net/virtio-net.c
15
@@ -XXX,XX +XXX,XX @@ static int virtio_net_post_load_device(void *opaque, int version_id)
16
}
17
}
18
19
+ if (n->rss_data.enabled) {
20
+ trace_virtio_net_rss_enable(n->rss_data.hash_types,
21
+ n->rss_data.indirections_len,
22
+ sizeof(n->rss_data.key));
23
+ } else {
24
+ trace_virtio_net_rss_disable();
25
+ }
26
return 0;
27
}
28
29
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_virtio_net_has_vnet = {
30
},
31
};
32
33
+static bool virtio_net_rss_needed(void *opaque)
34
+{
35
+ return VIRTIO_NET(opaque)->rss_data.enabled;
36
+}
37
+
38
+static const VMStateDescription vmstate_virtio_net_rss = {
39
+ .name = "virtio-net-device/rss",
40
+ .version_id = 1,
41
+ .minimum_version_id = 1,
42
+ .needed = virtio_net_rss_needed,
43
+ .fields = (VMStateField[]) {
44
+ VMSTATE_BOOL(rss_data.enabled, VirtIONet),
45
+ VMSTATE_BOOL(rss_data.redirect, VirtIONet),
46
+ VMSTATE_BOOL(rss_data.populate_hash, VirtIONet),
47
+ VMSTATE_UINT32(rss_data.hash_types, VirtIONet),
48
+ VMSTATE_UINT16(rss_data.indirections_len, VirtIONet),
49
+ VMSTATE_UINT16(rss_data.default_queue, VirtIONet),
50
+ VMSTATE_UINT8_ARRAY(rss_data.key, VirtIONet,
51
+ VIRTIO_NET_RSS_MAX_KEY_SIZE),
52
+ VMSTATE_VARRAY_UINT16_ALLOC(rss_data.indirections_table, VirtIONet,
53
+ rss_data.indirections_len, 0,
54
+ vmstate_info_uint16, uint16_t),
55
+ VMSTATE_END_OF_LIST()
56
+ },
57
+};
58
+
59
static const VMStateDescription vmstate_virtio_net_device = {
60
.name = "virtio-net-device",
61
.version_id = VIRTIO_NET_VM_VERSION,
62
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_virtio_net_device = {
63
has_ctrl_guest_offloads),
64
VMSTATE_END_OF_LIST()
65
},
66
+ .subsections = (const VMStateDescription * []) {
67
+ &vmstate_virtio_net_rss,
68
+ NULL
69
+ }
70
};
71
72
static NetClientInfo net_virtio_info = {
73
--
74
2.5.0
75
76
diff view generated by jsdifflib
New patch
1
From: Yuri Benditovich <yuri.benditovich@daynix.com>
1
2
3
Removal of duplicated RSC definitions. Changing names of the
4
fields to ones defined in the Linux header.
5
6
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
9
hw/net/virtio-net.c | 28 ++++------------------------
10
1 file changed, 4 insertions(+), 24 deletions(-)
11
12
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/net/virtio-net.c
15
+++ b/hw/net/virtio-net.c
16
@@ -XXX,XX +XXX,XX @@
17
VIRTIO_NET_RSS_HASH_TYPE_TCP_EX | \
18
VIRTIO_NET_RSS_HASH_TYPE_UDP_EX)
19
20
-/* temporary until standard header include it */
21
-#if !defined(VIRTIO_NET_HDR_F_RSC_INFO)
22
-
23
-#define VIRTIO_NET_HDR_F_RSC_INFO 4 /* rsc_ext data in csum_ fields */
24
-#define VIRTIO_NET_F_RSC_EXT 61
25
-
26
-#endif
27
-
28
-static inline __virtio16 *virtio_net_rsc_ext_num_packets(
29
- struct virtio_net_hdr *hdr)
30
-{
31
- return &hdr->csum_start;
32
-}
33
-
34
-static inline __virtio16 *virtio_net_rsc_ext_num_dupacks(
35
- struct virtio_net_hdr *hdr)
36
-{
37
- return &hdr->csum_offset;
38
-}
39
-
40
static VirtIOFeature feature_sizes[] = {
41
{.flags = 1ULL << VIRTIO_NET_F_MAC,
42
.end = endof(struct virtio_net_config, mac)},
43
@@ -XXX,XX +XXX,XX @@ static size_t virtio_net_rsc_drain_seg(VirtioNetRscChain *chain,
44
VirtioNetRscSeg *seg)
45
{
46
int ret;
47
- struct virtio_net_hdr *h;
48
+ struct virtio_net_hdr_v1 *h;
49
50
- h = (struct virtio_net_hdr *)seg->buf;
51
+ h = (struct virtio_net_hdr_v1 *)seg->buf;
52
h->flags = 0;
53
h->gso_type = VIRTIO_NET_HDR_GSO_NONE;
54
55
if (seg->is_coalesced) {
56
- *virtio_net_rsc_ext_num_packets(h) = seg->packets;
57
- *virtio_net_rsc_ext_num_dupacks(h) = seg->dup_ack;
58
+ h->rsc.segments = seg->packets;
59
+ h->rsc.dup_acks = seg->dup_ack;
60
h->flags = VIRTIO_NET_HDR_F_RSC_INFO;
61
if (chain->proto == ETH_P_IP) {
62
h->gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
63
--
64
2.5.0
65
66
diff view generated by jsdifflib
New patch
1
From: Helge Deller <deller@gmx.de>
1
2
3
The tulip network driver in a qemu-system-hppa emulation is broken in
4
the sense that bigger network packages aren't received any longer and
5
thus even running e.g. "apt update" inside the VM fails.
6
7
The breakage was introduced by commit 8ffb7265af ("check frame size and
8
r/w data length") which added checks to prevent accesses outside of the
9
rx/tx buffers.
10
11
But the new checks were implemented wrong. The variable rx_frame_len
12
counts backwards, from rx_frame_size down to zero, and the variable len
13
is never bigger than rx_frame_len, so accesses just can't happen and the
14
checks are unnecessary.
15
On the contrary the checks now prevented bigger packages to be moved
16
into the rx buffers.
17
18
This patch reverts the wrong checks and were sucessfully tested with a
19
qemu-system-hppa emulation.
20
21
Fixes: 8ffb7265af ("check frame size and r/w data length")
22
Buglink: https://bugs.launchpad.net/bugs/1874539
23
Signed-off-by: Helge Deller <deller@gmx.de>
24
Signed-off-by: Jason Wang <jasowang@redhat.com>
25
---
26
hw/net/tulip.c | 6 ------
27
1 file changed, 6 deletions(-)
28
29
diff --git a/hw/net/tulip.c b/hw/net/tulip.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/net/tulip.c
32
+++ b/hw/net/tulip.c
33
@@ -XXX,XX +XXX,XX @@ static void tulip_copy_rx_bytes(TULIPState *s, struct tulip_descriptor *desc)
34
len = s->rx_frame_len;
35
}
36
37
- if (s->rx_frame_len + len > sizeof(s->rx_frame)) {
38
- return;
39
- }
40
pci_dma_write(&s->dev, desc->buf_addr1, s->rx_frame +
41
(s->rx_frame_size - s->rx_frame_len), len);
42
s->rx_frame_len -= len;
43
@@ -XXX,XX +XXX,XX @@ static void tulip_copy_rx_bytes(TULIPState *s, struct tulip_descriptor *desc)
44
len = s->rx_frame_len;
45
}
46
47
- if (s->rx_frame_len + len > sizeof(s->rx_frame)) {
48
- return;
49
- }
50
pci_dma_write(&s->dev, desc->buf_addr2, s->rx_frame +
51
(s->rx_frame_size - s->rx_frame_len), len);
52
s->rx_frame_len -= len;
53
--
54
2.5.0
55
56
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
Bit #14 is "DE" for 'Descriptor Error':
4
5
When set, indicates a frame truncation caused by a frame
6
that does not fit within the current descriptor buffers,
7
and that the 21143 does not own the next descriptor.
8
9
[Table 4-1. RDES0 Bit Fields Description]
10
11
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
---
14
hw/net/tulip.h | 2 +-
15
1 file changed, 1 insertion(+), 1 deletion(-)
16
17
diff --git a/hw/net/tulip.h b/hw/net/tulip.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/net/tulip.h
20
+++ b/hw/net/tulip.h
21
@@ -XXX,XX +XXX,XX @@
22
#define RDES0_RF BIT(11)
23
#define RDES0_DT_SHIFT 12
24
#define RDES0_DT_MASK 3
25
-#define RDES0_LE BIT(14)
26
+#define RDES0_DE BIT(14)
27
#define RDES0_ES BIT(15)
28
#define RDES0_FL_SHIFT 16
29
#define RDES0_FL_MASK 0x3fff
30
--
31
2.5.0
32
33
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
Log with GUEST_ERROR what the guest is doing wrong.
4
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
---
8
hw/net/tulip.c | 6 ++++++
9
1 file changed, 6 insertions(+)
10
11
diff --git a/hw/net/tulip.c b/hw/net/tulip.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/net/tulip.c
14
+++ b/hw/net/tulip.c
15
@@ -XXX,XX +XXX,XX @@ static int tulip_copy_tx_buffers(TULIPState *s, struct tulip_descriptor *desc)
16
int len2 = (desc->control >> TDES1_BUF2_SIZE_SHIFT) & TDES1_BUF2_SIZE_MASK;
17
18
if (s->tx_frame_len + len1 > sizeof(s->tx_frame)) {
19
+ qemu_log_mask(LOG_GUEST_ERROR,
20
+ "%s: descriptor overflow (ofs: %u, len:%d, size:%zu)\n",
21
+ __func__, s->tx_frame_len, len1, sizeof(s->tx_frame));
22
return -1;
23
}
24
if (len1) {
25
@@ -XXX,XX +XXX,XX @@ static int tulip_copy_tx_buffers(TULIPState *s, struct tulip_descriptor *desc)
26
}
27
28
if (s->tx_frame_len + len2 > sizeof(s->tx_frame)) {
29
+ qemu_log_mask(LOG_GUEST_ERROR,
30
+ "%s: descriptor overflow (ofs: %u, len:%d, size:%zu)\n",
31
+ __func__, s->tx_frame_len, len2, sizeof(s->tx_frame));
32
return -1;
33
}
34
if (len2) {
35
--
36
2.5.0
37
38
diff view generated by jsdifflib
New patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
1
2
3
Enabling debug breaks the build, Fix them and make debug statements
4
always compilable. Fix few statements to use sized integer casting.
5
6
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
7
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
10
hw/net/cadence_gem.c | 27 +++++++++++++--------------
11
1 file changed, 13 insertions(+), 14 deletions(-)
12
13
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/net/cadence_gem.c
16
+++ b/hw/net/cadence_gem.c
17
@@ -XXX,XX +XXX,XX @@
18
#include "sysemu/dma.h"
19
#include "net/checksum.h"
20
21
-#ifdef CADENCE_GEM_ERR_DEBUG
22
-#define DB_PRINT(...) do { \
23
- fprintf(stderr, ": %s: ", __func__); \
24
- fprintf(stderr, ## __VA_ARGS__); \
25
- } while (0)
26
-#else
27
- #define DB_PRINT(...)
28
-#endif
29
+#define CADENCE_GEM_ERR_DEBUG 0
30
+#define DB_PRINT(...) do {\
31
+ if (CADENCE_GEM_ERR_DEBUG) { \
32
+ qemu_log(": %s: ", __func__); \
33
+ qemu_log(__VA_ARGS__); \
34
+ } \
35
+} while (0)
36
37
#define GEM_NWCTRL (0x00000000/4) /* Network Control reg */
38
#define GEM_NWCFG (0x00000004/4) /* Network Config reg */
39
@@ -XXX,XX +XXX,XX @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
40
size += 4;
41
}
42
43
- DB_PRINT("config bufsize: %d packet size: %ld\n", rxbufsize, size);
44
+ DB_PRINT("config bufsize: %u packet size: %zd\n", rxbufsize, size);
45
46
/* Find which queue we are targeting */
47
q = get_queue_from_screen(s, rxbuf_ptr, rxbufsize);
48
@@ -XXX,XX +XXX,XX @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
49
return -1;
50
}
51
52
- DB_PRINT("copy %u bytes to 0x%" PRIx64 "\n",
53
- MIN(bytes_to_copy, rxbufsize),
54
- rx_desc_get_buffer(s, s->rx_desc[q]));
55
+ DB_PRINT("copy %" PRIu32 " bytes to 0x%" PRIx64 "\n",
56
+ MIN(bytes_to_copy, rxbufsize),
57
+ rx_desc_get_buffer(s, s->rx_desc[q]));
58
59
/* Copy packet data to emulated DMA buffer */
60
address_space_write(&s->dma_as, rx_desc_get_buffer(s, s->rx_desc[q]) +
61
@@ -XXX,XX +XXX,XX @@ static void gem_transmit(CadenceGEMState *s)
62
*/
63
if ((tx_desc_get_buffer(s, desc) == 0) ||
64
(tx_desc_get_length(desc) == 0)) {
65
- DB_PRINT("Invalid TX descriptor @ 0x%x\n",
66
- (unsigned)packet_desc_addr);
67
+ DB_PRINT("Invalid TX descriptor @ 0x%" HWADDR_PRIx "\n",
68
+ packet_desc_addr);
69
break;
70
}
71
72
--
73
2.5.0
74
75
diff view generated by jsdifflib
New patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
1
2
3
During wrap around and reset, queues are pointing to initial base
4
address of queue 0, irrespective of what queue we are dealing with.
5
Fix it by assigning proper base address every time.
6
7
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
11
hw/net/cadence_gem.c | 37 +++++++++++++++++++++++++++++++++----
12
1 file changed, 33 insertions(+), 4 deletions(-)
13
14
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/net/cadence_gem.c
17
+++ b/hw/net/cadence_gem.c
18
@@ -XXX,XX +XXX,XX @@ static int get_queue_from_screen(CadenceGEMState *s, uint8_t *rxbuf_ptr,
19
return 0;
20
}
21
22
+static uint32_t gem_get_queue_base_addr(CadenceGEMState *s, bool tx, int q)
23
+{
24
+ uint32_t base_addr = 0;
25
+
26
+ switch (q) {
27
+ case 0:
28
+ base_addr = s->regs[tx ? GEM_TXQBASE : GEM_RXQBASE];
29
+ break;
30
+ case 1 ... (MAX_PRIORITY_QUEUES - 1):
31
+ base_addr = s->regs[(tx ? GEM_TRANSMIT_Q1_PTR :
32
+ GEM_RECEIVE_Q1_PTR) + q - 1];
33
+ break;
34
+ default:
35
+ g_assert_not_reached();
36
+ };
37
+
38
+ return base_addr;
39
+}
40
+
41
+static inline uint32_t gem_get_tx_queue_base_addr(CadenceGEMState *s, int q)
42
+{
43
+ return gem_get_queue_base_addr(s, true, q);
44
+}
45
+
46
+static inline uint32_t gem_get_rx_queue_base_addr(CadenceGEMState *s, int q)
47
+{
48
+ return gem_get_queue_base_addr(s, false, q);
49
+}
50
+
51
static hwaddr gem_get_desc_addr(CadenceGEMState *s, bool tx, int q)
52
{
53
hwaddr desc_addr = 0;
54
@@ -XXX,XX +XXX,XX @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
55
/* Next descriptor */
56
if (rx_desc_get_wrap(s->rx_desc[q])) {
57
DB_PRINT("wrapping RX descriptor list\n");
58
- s->rx_desc_addr[q] = s->regs[GEM_RXQBASE];
59
+ s->rx_desc_addr[q] = gem_get_rx_queue_base_addr(s, q);
60
} else {
61
DB_PRINT("incrementing RX descriptor list\n");
62
s->rx_desc_addr[q] += 4 * gem_get_desc_len(s, true);
63
@@ -XXX,XX +XXX,XX @@ static void gem_transmit(CadenceGEMState *s)
64
sizeof(desc_first));
65
/* Advance the hardware current descriptor past this packet */
66
if (tx_desc_get_wrap(desc)) {
67
- s->tx_desc_addr[q] = s->regs[GEM_TXQBASE];
68
+ s->tx_desc_addr[q] = gem_get_tx_queue_base_addr(s, q);
69
} else {
70
s->tx_desc_addr[q] = packet_desc_addr +
71
4 * gem_get_desc_len(s, false);
72
@@ -XXX,XX +XXX,XX @@ static void gem_transmit(CadenceGEMState *s)
73
} else {
74
packet_desc_addr = 0;
75
}
76
- packet_desc_addr |= s->regs[GEM_TXQBASE];
77
+ packet_desc_addr |= gem_get_tx_queue_base_addr(s, q);
78
} else {
79
packet_desc_addr += 4 * gem_get_desc_len(s, false);
80
}
81
@@ -XXX,XX +XXX,XX @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
82
if (!(val & GEM_NWCTRL_TXENA)) {
83
/* Reset to start of Q when transmit disabled. */
84
for (i = 0; i < s->num_priority_queues; i++) {
85
- s->tx_desc_addr[i] = s->regs[GEM_TXQBASE];
86
+ s->tx_desc_addr[i] = gem_get_tx_queue_base_addr(s, i);
87
}
88
}
89
if (gem_can_receive(qemu_get_queue(s->nic))) {
90
--
91
2.5.0
92
93
diff view generated by jsdifflib
New patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
1
2
3
Set irq's specific to a queue, present implementation is setting q1 irq
4
based on q0 status.
5
6
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
7
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
10
hw/net/cadence_gem.c | 25 +++----------------------
11
1 file changed, 3 insertions(+), 22 deletions(-)
12
13
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/net/cadence_gem.c
16
+++ b/hw/net/cadence_gem.c
17
@@ -XXX,XX +XXX,XX @@ static void gem_update_int_status(CadenceGEMState *s)
18
{
19
int i;
20
21
- if (!s->regs[GEM_ISR]) {
22
- /* ISR isn't set, clear all the interrupts */
23
- for (i = 0; i < s->num_priority_queues; ++i) {
24
- qemu_set_irq(s->irq[i], 0);
25
- }
26
- return;
27
- }
28
+ qemu_set_irq(s->irq[0], !!s->regs[GEM_ISR]);
29
30
- /* If we get here we know s->regs[GEM_ISR] is set, so we don't need to
31
- * check it again.
32
- */
33
- if (s->num_priority_queues == 1) {
34
- /* No priority queues, just trigger the interrupt */
35
- DB_PRINT("asserting int.\n");
36
- qemu_set_irq(s->irq[0], 1);
37
- return;
38
- }
39
-
40
- for (i = 0; i < s->num_priority_queues; ++i) {
41
- if (s->regs[GEM_INT_Q1_STATUS + i]) {
42
- DB_PRINT("asserting int. (q=%d)\n", i);
43
- qemu_set_irq(s->irq[i], 1);
44
- }
45
+ for (i = 1; i < s->num_priority_queues; ++i) {
46
+ qemu_set_irq(s->irq[i], !!s->regs[GEM_INT_Q1_STATUS + i - 1]);
47
}
48
}
49
50
--
51
2.5.0
52
53
diff view generated by jsdifflib
New patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
1
2
3
Q1 to Q7 ISR's are clear-on-read, IER/IDR registers
4
are write-only, mask reg are read-only.
5
6
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
7
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
10
hw/net/cadence_gem.c | 14 ++++++++++++++
11
1 file changed, 14 insertions(+)
12
13
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/net/cadence_gem.c
16
+++ b/hw/net/cadence_gem.c
17
@@ -XXX,XX +XXX,XX @@ static const uint8_t broadcast_addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
18
*/
19
static void gem_init_register_masks(CadenceGEMState *s)
20
{
21
+ unsigned int i;
22
/* Mask of register bits which are read only */
23
memset(&s->regs_ro[0], 0, sizeof(s->regs_ro));
24
s->regs_ro[GEM_NWCTRL] = 0xFFF80000;
25
@@ -XXX,XX +XXX,XX @@ static void gem_init_register_masks(CadenceGEMState *s)
26
s->regs_ro[GEM_ISR] = 0xFFFFFFFF;
27
s->regs_ro[GEM_IMR] = 0xFFFFFFFF;
28
s->regs_ro[GEM_MODID] = 0xFFFFFFFF;
29
+ for (i = 0; i < s->num_priority_queues; i++) {
30
+ s->regs_ro[GEM_INT_Q1_STATUS + i] = 0xFFFFFFFF;
31
+ s->regs_ro[GEM_INT_Q1_ENABLE + i] = 0xFFFFF319;
32
+ s->regs_ro[GEM_INT_Q1_DISABLE + i] = 0xFFFFF319;
33
+ s->regs_ro[GEM_INT_Q1_MASK + i] = 0xFFFFFFFF;
34
+ }
35
36
/* Mask of register bits which are clear on read */
37
memset(&s->regs_rtc[0], 0, sizeof(s->regs_rtc));
38
s->regs_rtc[GEM_ISR] = 0xFFFFFFFF;
39
+ for (i = 0; i < s->num_priority_queues; i++) {
40
+ s->regs_rtc[GEM_INT_Q1_STATUS + i] = 0x00000CE6;
41
+ }
42
43
/* Mask of register bits which are write 1 to clear */
44
memset(&s->regs_w1c[0], 0, sizeof(s->regs_w1c));
45
@@ -XXX,XX +XXX,XX @@ static void gem_init_register_masks(CadenceGEMState *s)
46
s->regs_wo[GEM_NWCTRL] = 0x00073E60;
47
s->regs_wo[GEM_IER] = 0x07FFFFFF;
48
s->regs_wo[GEM_IDR] = 0x07FFFFFF;
49
+ for (i = 0; i < s->num_priority_queues; i++) {
50
+ s->regs_wo[GEM_INT_Q1_ENABLE + i] = 0x00000CE6;
51
+ s->regs_wo[GEM_INT_Q1_DISABLE + i] = 0x00000CE6;
52
+ }
53
}
54
55
/*
56
--
57
2.5.0
58
59
diff view generated by jsdifflib
New patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
1
2
3
Set ISR according to queue in use, added interrupt support for
4
all queues.
5
6
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
7
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
10
hw/net/cadence_gem.c | 27 +++++++++++++++++----------
11
1 file changed, 17 insertions(+), 10 deletions(-)
12
13
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/net/cadence_gem.c
16
+++ b/hw/net/cadence_gem.c
17
@@ -XXX,XX +XXX,XX @@ static inline void rx_desc_set_sar(uint32_t *desc, int sar_idx)
18
/* The broadcast MAC address: 0xFFFFFFFFFFFF */
19
static const uint8_t broadcast_addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
20
21
+static void gem_set_isr(CadenceGEMState *s, int q, uint32_t flag)
22
+{
23
+ if (q == 0) {
24
+ s->regs[GEM_ISR] |= flag & ~(s->regs[GEM_IMR]);
25
+ } else {
26
+ s->regs[GEM_INT_Q1_STATUS + q - 1] |= flag &
27
+ ~(s->regs[GEM_INT_Q1_MASK + q - 1]);
28
+ }
29
+}
30
+
31
/*
32
* gem_init_register_masks:
33
* One time initialization.
34
@@ -XXX,XX +XXX,XX @@ static void gem_get_rx_desc(CadenceGEMState *s, int q)
35
if (rx_desc_get_ownership(s->rx_desc[q]) == 1) {
36
DB_PRINT("descriptor 0x%" HWADDR_PRIx " owned by sw.\n", desc_addr);
37
s->regs[GEM_RXSTATUS] |= GEM_RXSTATUS_NOBUF;
38
- s->regs[GEM_ISR] |= GEM_INT_RXUSED & ~(s->regs[GEM_IMR]);
39
+ gem_set_isr(s, q, GEM_INT_RXUSED);
40
/* Handle interrupt consequences */
41
gem_update_int_status(s);
42
}
43
@@ -XXX,XX +XXX,XX @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
44
gem_receive_updatestats(s, buf, size);
45
46
s->regs[GEM_RXSTATUS] |= GEM_RXSTATUS_FRMRCVD;
47
- s->regs[GEM_ISR] |= GEM_INT_RXCMPL & ~(s->regs[GEM_IMR]);
48
+ gem_set_isr(s, q, GEM_INT_RXCMPL);
49
50
/* Handle interrupt consequences */
51
gem_update_int_status(s);
52
@@ -XXX,XX +XXX,XX @@ static void gem_transmit(CadenceGEMState *s)
53
DB_PRINT("TX descriptor next: 0x%08x\n", s->tx_desc_addr[q]);
54
55
s->regs[GEM_TXSTATUS] |= GEM_TXSTATUS_TXCMPL;
56
- s->regs[GEM_ISR] |= GEM_INT_TXCMPL & ~(s->regs[GEM_IMR]);
57
-
58
- /* Update queue interrupt status */
59
- if (s->num_priority_queues > 1) {
60
- s->regs[GEM_INT_Q1_STATUS + q] |=
61
- GEM_INT_TXCMPL & ~(s->regs[GEM_INT_Q1_MASK + q]);
62
- }
63
+ gem_set_isr(s, q, GEM_INT_TXCMPL);
64
65
/* Handle interrupt consequences */
66
gem_update_int_status(s);
67
@@ -XXX,XX +XXX,XX @@ static void gem_transmit(CadenceGEMState *s)
68
69
if (tx_desc_get_used(desc)) {
70
s->regs[GEM_TXSTATUS] |= GEM_TXSTATUS_USED;
71
- s->regs[GEM_ISR] |= GEM_INT_TXUSED & ~(s->regs[GEM_IMR]);
72
+ /* IRQ TXUSED is defined only for queue 0 */
73
+ if (q == 0) {
74
+ gem_set_isr(s, 0, GEM_INT_TXUSED);
75
+ }
76
gem_update_int_status(s);
77
}
78
}
79
--
80
2.5.0
81
82
diff view generated by jsdifflib
New patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
1
2
3
Moving this buffers to CadenceGEMState, as their size will be increased
4
more when JUMBO frames support is added.
5
6
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
7
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
10
hw/net/cadence_gem.c | 38 +++++++++++++++++---------------------
11
include/hw/net/cadence_gem.h | 4 ++++
12
2 files changed, 21 insertions(+), 21 deletions(-)
13
14
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/net/cadence_gem.c
17
+++ b/hw/net/cadence_gem.c
18
@@ -XXX,XX +XXX,XX @@ static void gem_get_rx_desc(CadenceGEMState *s, int q)
19
*/
20
static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
21
{
22
- CadenceGEMState *s;
23
+ CadenceGEMState *s = qemu_get_nic_opaque(nc);
24
unsigned rxbufsize, bytes_to_copy;
25
unsigned rxbuf_offset;
26
- uint8_t rxbuf[2048];
27
uint8_t *rxbuf_ptr;
28
bool first_desc = true;
29
int maf;
30
int q = 0;
31
32
- s = qemu_get_nic_opaque(nc);
33
-
34
/* Is this destination MAC address "for us" ? */
35
maf = gem_mac_address_filter(s, buf);
36
if (maf == GEM_RX_REJECT) {
37
@@ -XXX,XX +XXX,XX @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
38
} else {
39
unsigned crc_val;
40
41
- if (size > sizeof(rxbuf) - sizeof(crc_val)) {
42
- size = sizeof(rxbuf) - sizeof(crc_val);
43
+ if (size > MAX_FRAME_SIZE - sizeof(crc_val)) {
44
+ size = MAX_FRAME_SIZE - sizeof(crc_val);
45
}
46
bytes_to_copy = size;
47
/* The application wants the FCS field, which QEMU does not provide.
48
* We must try and calculate one.
49
*/
50
51
- memcpy(rxbuf, buf, size);
52
- memset(rxbuf + size, 0, sizeof(rxbuf) - size);
53
- rxbuf_ptr = rxbuf;
54
- crc_val = cpu_to_le32(crc32(0, rxbuf, MAX(size, 60)));
55
- memcpy(rxbuf + size, &crc_val, sizeof(crc_val));
56
+ memcpy(s->rx_packet, buf, size);
57
+ memset(s->rx_packet + size, 0, MAX_FRAME_SIZE - size);
58
+ rxbuf_ptr = s->rx_packet;
59
+ crc_val = cpu_to_le32(crc32(0, s->rx_packet, MAX(size, 60)));
60
+ memcpy(s->rx_packet + size, &crc_val, sizeof(crc_val));
61
62
bytes_to_copy += 4;
63
size += 4;
64
@@ -XXX,XX +XXX,XX @@ static void gem_transmit(CadenceGEMState *s)
65
{
66
uint32_t desc[DESC_MAX_NUM_WORDS];
67
hwaddr packet_desc_addr;
68
- uint8_t tx_packet[2048];
69
uint8_t *p;
70
unsigned total_bytes;
71
int q = 0;
72
@@ -XXX,XX +XXX,XX @@ static void gem_transmit(CadenceGEMState *s)
73
* Packets scattered across multiple descriptors are gathered to this
74
* one contiguous buffer first.
75
*/
76
- p = tx_packet;
77
+ p = s->tx_packet;
78
total_bytes = 0;
79
80
for (q = s->num_priority_queues - 1; q >= 0; q--) {
81
@@ -XXX,XX +XXX,XX @@ static void gem_transmit(CadenceGEMState *s)
82
break;
83
}
84
85
- if (tx_desc_get_length(desc) > sizeof(tx_packet) -
86
- (p - tx_packet)) {
87
+ if (tx_desc_get_length(desc) > MAX_FRAME_SIZE -
88
+ (p - s->tx_packet)) {
89
DB_PRINT("TX descriptor @ 0x%" HWADDR_PRIx \
90
" too large: size 0x%x space 0x%zx\n",
91
packet_desc_addr, tx_desc_get_length(desc),
92
- sizeof(tx_packet) - (p - tx_packet));
93
+ MAX_FRAME_SIZE - (p - s->tx_packet));
94
break;
95
}
96
97
@@ -XXX,XX +XXX,XX @@ static void gem_transmit(CadenceGEMState *s)
98
99
/* Is checksum offload enabled? */
100
if (s->regs[GEM_DMACFG] & GEM_DMACFG_TXCSUM_OFFL) {
101
- net_checksum_calculate(tx_packet, total_bytes);
102
+ net_checksum_calculate(s->tx_packet, total_bytes);
103
}
104
105
/* Update MAC statistics */
106
- gem_transmit_updatestats(s, tx_packet, total_bytes);
107
+ gem_transmit_updatestats(s, s->tx_packet, total_bytes);
108
109
/* Send the packet somewhere */
110
if (s->phy_loop || (s->regs[GEM_NWCTRL] &
111
GEM_NWCTRL_LOCALLOOP)) {
112
- gem_receive(qemu_get_queue(s->nic), tx_packet,
113
+ gem_receive(qemu_get_queue(s->nic), s->tx_packet,
114
total_bytes);
115
} else {
116
- qemu_send_packet(qemu_get_queue(s->nic), tx_packet,
117
+ qemu_send_packet(qemu_get_queue(s->nic), s->tx_packet,
118
total_bytes);
119
}
120
121
/* Prepare for next packet */
122
- p = tx_packet;
123
+ p = s->tx_packet;
124
total_bytes = 0;
125
}
126
127
diff --git a/include/hw/net/cadence_gem.h b/include/hw/net/cadence_gem.h
128
index XXXXXXX..XXXXXXX 100644
129
--- a/include/hw/net/cadence_gem.h
130
+++ b/include/hw/net/cadence_gem.h
131
@@ -XXX,XX +XXX,XX @@
132
#define MAX_TYPE1_SCREENERS 16
133
#define MAX_TYPE2_SCREENERS 16
134
135
+#define MAX_FRAME_SIZE 2048
136
+
137
typedef struct CadenceGEMState {
138
/*< private >*/
139
SysBusDevice parent_obj;
140
@@ -XXX,XX +XXX,XX @@ typedef struct CadenceGEMState {
141
142
uint8_t can_rx_state; /* Debug only */
143
144
+ uint8_t tx_packet[MAX_FRAME_SIZE];
145
+ uint8_t rx_packet[MAX_FRAME_SIZE];
146
uint32_t rx_desc[MAX_PRIORITY_QUEUES][DESC_MAX_NUM_WORDS];
147
148
bool sar_active[4];
149
--
150
2.5.0
151
152
diff view generated by jsdifflib
New patch
1
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
2
3
Fix the code style for register definitions.
4
5
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
9
hw/net/cadence_gem.c | 204 ++++++++++++++++++++++++++-------------------------
10
1 file changed, 103 insertions(+), 101 deletions(-)
11
12
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/net/cadence_gem.c
15
+++ b/hw/net/cadence_gem.c
16
@@ -XXX,XX +XXX,XX @@
17
} \
18
} while (0)
19
20
-#define GEM_NWCTRL (0x00000000/4) /* Network Control reg */
21
-#define GEM_NWCFG (0x00000004/4) /* Network Config reg */
22
-#define GEM_NWSTATUS (0x00000008/4) /* Network Status reg */
23
-#define GEM_USERIO (0x0000000C/4) /* User IO reg */
24
-#define GEM_DMACFG (0x00000010/4) /* DMA Control reg */
25
-#define GEM_TXSTATUS (0x00000014/4) /* TX Status reg */
26
-#define GEM_RXQBASE (0x00000018/4) /* RX Q Base address reg */
27
-#define GEM_TXQBASE (0x0000001C/4) /* TX Q Base address reg */
28
-#define GEM_RXSTATUS (0x00000020/4) /* RX Status reg */
29
-#define GEM_ISR (0x00000024/4) /* Interrupt Status reg */
30
-#define GEM_IER (0x00000028/4) /* Interrupt Enable reg */
31
-#define GEM_IDR (0x0000002C/4) /* Interrupt Disable reg */
32
-#define GEM_IMR (0x00000030/4) /* Interrupt Mask reg */
33
-#define GEM_PHYMNTNC (0x00000034/4) /* Phy Maintenance reg */
34
-#define GEM_RXPAUSE (0x00000038/4) /* RX Pause Time reg */
35
-#define GEM_TXPAUSE (0x0000003C/4) /* TX Pause Time reg */
36
-#define GEM_TXPARTIALSF (0x00000040/4) /* TX Partial Store and Forward */
37
-#define GEM_RXPARTIALSF (0x00000044/4) /* RX Partial Store and Forward */
38
-#define GEM_HASHLO (0x00000080/4) /* Hash Low address reg */
39
-#define GEM_HASHHI (0x00000084/4) /* Hash High address reg */
40
-#define GEM_SPADDR1LO (0x00000088/4) /* Specific addr 1 low reg */
41
-#define GEM_SPADDR1HI (0x0000008C/4) /* Specific addr 1 high reg */
42
-#define GEM_SPADDR2LO (0x00000090/4) /* Specific addr 2 low reg */
43
-#define GEM_SPADDR2HI (0x00000094/4) /* Specific addr 2 high reg */
44
-#define GEM_SPADDR3LO (0x00000098/4) /* Specific addr 3 low reg */
45
-#define GEM_SPADDR3HI (0x0000009C/4) /* Specific addr 3 high reg */
46
-#define GEM_SPADDR4LO (0x000000A0/4) /* Specific addr 4 low reg */
47
-#define GEM_SPADDR4HI (0x000000A4/4) /* Specific addr 4 high reg */
48
-#define GEM_TIDMATCH1 (0x000000A8/4) /* Type ID1 Match reg */
49
-#define GEM_TIDMATCH2 (0x000000AC/4) /* Type ID2 Match reg */
50
-#define GEM_TIDMATCH3 (0x000000B0/4) /* Type ID3 Match reg */
51
-#define GEM_TIDMATCH4 (0x000000B4/4) /* Type ID4 Match reg */
52
-#define GEM_WOLAN (0x000000B8/4) /* Wake on LAN reg */
53
-#define GEM_IPGSTRETCH (0x000000BC/4) /* IPG Stretch reg */
54
-#define GEM_SVLAN (0x000000C0/4) /* Stacked VLAN reg */
55
-#define GEM_MODID (0x000000FC/4) /* Module ID reg */
56
-#define GEM_OCTTXLO (0x00000100/4) /* Octects transmitted Low reg */
57
-#define GEM_OCTTXHI (0x00000104/4) /* Octects transmitted High reg */
58
-#define GEM_TXCNT (0x00000108/4) /* Error-free Frames transmitted */
59
-#define GEM_TXBCNT (0x0000010C/4) /* Error-free Broadcast Frames */
60
-#define GEM_TXMCNT (0x00000110/4) /* Error-free Multicast Frame */
61
-#define GEM_TXPAUSECNT (0x00000114/4) /* Pause Frames Transmitted */
62
-#define GEM_TX64CNT (0x00000118/4) /* Error-free 64 TX */
63
-#define GEM_TX65CNT (0x0000011C/4) /* Error-free 65-127 TX */
64
-#define GEM_TX128CNT (0x00000120/4) /* Error-free 128-255 TX */
65
-#define GEM_TX256CNT (0x00000124/4) /* Error-free 256-511 */
66
-#define GEM_TX512CNT (0x00000128/4) /* Error-free 512-1023 TX */
67
-#define GEM_TX1024CNT (0x0000012C/4) /* Error-free 1024-1518 TX */
68
-#define GEM_TX1519CNT (0x00000130/4) /* Error-free larger than 1519 TX */
69
-#define GEM_TXURUNCNT (0x00000134/4) /* TX under run error counter */
70
-#define GEM_SINGLECOLLCNT (0x00000138/4) /* Single Collision Frames */
71
-#define GEM_MULTCOLLCNT (0x0000013C/4) /* Multiple Collision Frames */
72
-#define GEM_EXCESSCOLLCNT (0x00000140/4) /* Excessive Collision Frames */
73
-#define GEM_LATECOLLCNT (0x00000144/4) /* Late Collision Frames */
74
-#define GEM_DEFERTXCNT (0x00000148/4) /* Deferred Transmission Frames */
75
-#define GEM_CSENSECNT (0x0000014C/4) /* Carrier Sense Error Counter */
76
-#define GEM_OCTRXLO (0x00000150/4) /* Octects Received register Low */
77
-#define GEM_OCTRXHI (0x00000154/4) /* Octects Received register High */
78
-#define GEM_RXCNT (0x00000158/4) /* Error-free Frames Received */
79
-#define GEM_RXBROADCNT (0x0000015C/4) /* Error-free Broadcast Frames RX */
80
-#define GEM_RXMULTICNT (0x00000160/4) /* Error-free Multicast Frames RX */
81
-#define GEM_RXPAUSECNT (0x00000164/4) /* Pause Frames Received Counter */
82
-#define GEM_RX64CNT (0x00000168/4) /* Error-free 64 byte Frames RX */
83
-#define GEM_RX65CNT (0x0000016C/4) /* Error-free 65-127B Frames RX */
84
-#define GEM_RX128CNT (0x00000170/4) /* Error-free 128-255B Frames RX */
85
-#define GEM_RX256CNT (0x00000174/4) /* Error-free 256-512B Frames RX */
86
-#define GEM_RX512CNT (0x00000178/4) /* Error-free 512-1023B Frames RX */
87
-#define GEM_RX1024CNT (0x0000017C/4) /* Error-free 1024-1518B Frames RX */
88
-#define GEM_RX1519CNT (0x00000180/4) /* Error-free 1519-max Frames RX */
89
-#define GEM_RXUNDERCNT (0x00000184/4) /* Undersize Frames Received */
90
-#define GEM_RXOVERCNT (0x00000188/4) /* Oversize Frames Received */
91
-#define GEM_RXJABCNT (0x0000018C/4) /* Jabbers Received Counter */
92
-#define GEM_RXFCSCNT (0x00000190/4) /* Frame Check seq. Error Counter */
93
-#define GEM_RXLENERRCNT (0x00000194/4) /* Length Field Error Counter */
94
-#define GEM_RXSYMERRCNT (0x00000198/4) /* Symbol Error Counter */
95
-#define GEM_RXALIGNERRCNT (0x0000019C/4) /* Alignment Error Counter */
96
-#define GEM_RXRSCERRCNT (0x000001A0/4) /* Receive Resource Error Counter */
97
-#define GEM_RXORUNCNT (0x000001A4/4) /* Receive Overrun Counter */
98
-#define GEM_RXIPCSERRCNT (0x000001A8/4) /* IP header Checksum Error Counter */
99
-#define GEM_RXTCPCCNT (0x000001AC/4) /* TCP Checksum Error Counter */
100
-#define GEM_RXUDPCCNT (0x000001B0/4) /* UDP Checksum Error Counter */
101
-
102
-#define GEM_1588S (0x000001D0/4) /* 1588 Timer Seconds */
103
-#define GEM_1588NS (0x000001D4/4) /* 1588 Timer Nanoseconds */
104
-#define GEM_1588ADJ (0x000001D8/4) /* 1588 Timer Adjust */
105
-#define GEM_1588INC (0x000001DC/4) /* 1588 Timer Increment */
106
-#define GEM_PTPETXS (0x000001E0/4) /* PTP Event Frame Transmitted (s) */
107
-#define GEM_PTPETXNS (0x000001E4/4) /* PTP Event Frame Transmitted (ns) */
108
-#define GEM_PTPERXS (0x000001E8/4) /* PTP Event Frame Received (s) */
109
-#define GEM_PTPERXNS (0x000001EC/4) /* PTP Event Frame Received (ns) */
110
-#define GEM_PTPPTXS (0x000001E0/4) /* PTP Peer Frame Transmitted (s) */
111
-#define GEM_PTPPTXNS (0x000001E4/4) /* PTP Peer Frame Transmitted (ns) */
112
-#define GEM_PTPPRXS (0x000001E8/4) /* PTP Peer Frame Received (s) */
113
-#define GEM_PTPPRXNS (0x000001EC/4) /* PTP Peer Frame Received (ns) */
114
+#define GEM_NWCTRL (0x00000000 / 4) /* Network Control reg */
115
+#define GEM_NWCFG (0x00000004 / 4) /* Network Config reg */
116
+#define GEM_NWSTATUS (0x00000008 / 4) /* Network Status reg */
117
+#define GEM_USERIO (0x0000000C / 4) /* User IO reg */
118
+#define GEM_DMACFG (0x00000010 / 4) /* DMA Control reg */
119
+#define GEM_TXSTATUS (0x00000014 / 4) /* TX Status reg */
120
+#define GEM_RXQBASE (0x00000018 / 4) /* RX Q Base address reg */
121
+#define GEM_TXQBASE (0x0000001C / 4) /* TX Q Base address reg */
122
+#define GEM_RXSTATUS (0x00000020 / 4) /* RX Status reg */
123
+#define GEM_ISR (0x00000024 / 4) /* Interrupt Status reg */
124
+#define GEM_IER (0x00000028 / 4) /* Interrupt Enable reg */
125
+#define GEM_IDR (0x0000002C / 4) /* Interrupt Disable reg */
126
+#define GEM_IMR (0x00000030 / 4) /* Interrupt Mask reg */
127
+#define GEM_PHYMNTNC (0x00000034 / 4) /* Phy Maintenance reg */
128
+#define GEM_RXPAUSE (0x00000038 / 4) /* RX Pause Time reg */
129
+#define GEM_TXPAUSE (0x0000003C / 4) /* TX Pause Time reg */
130
+#define GEM_TXPARTIALSF (0x00000040 / 4) /* TX Partial Store and Forward */
131
+#define GEM_RXPARTIALSF (0x00000044 / 4) /* RX Partial Store and Forward */
132
+#define GEM_HASHLO (0x00000080 / 4) /* Hash Low address reg */
133
+#define GEM_HASHHI (0x00000084 / 4) /* Hash High address reg */
134
+#define GEM_SPADDR1LO (0x00000088 / 4) /* Specific addr 1 low reg */
135
+#define GEM_SPADDR1HI (0x0000008C / 4) /* Specific addr 1 high reg */
136
+#define GEM_SPADDR2LO (0x00000090 / 4) /* Specific addr 2 low reg */
137
+#define GEM_SPADDR2HI (0x00000094 / 4) /* Specific addr 2 high reg */
138
+#define GEM_SPADDR3LO (0x00000098 / 4) /* Specific addr 3 low reg */
139
+#define GEM_SPADDR3HI (0x0000009C / 4) /* Specific addr 3 high reg */
140
+#define GEM_SPADDR4LO (0x000000A0 / 4) /* Specific addr 4 low reg */
141
+#define GEM_SPADDR4HI (0x000000A4 / 4) /* Specific addr 4 high reg */
142
+#define GEM_TIDMATCH1 (0x000000A8 / 4) /* Type ID1 Match reg */
143
+#define GEM_TIDMATCH2 (0x000000AC / 4) /* Type ID2 Match reg */
144
+#define GEM_TIDMATCH3 (0x000000B0 / 4) /* Type ID3 Match reg */
145
+#define GEM_TIDMATCH4 (0x000000B4 / 4) /* Type ID4 Match reg */
146
+#define GEM_WOLAN (0x000000B8 / 4) /* Wake on LAN reg */
147
+#define GEM_IPGSTRETCH (0x000000BC / 4) /* IPG Stretch reg */
148
+#define GEM_SVLAN (0x000000C0 / 4) /* Stacked VLAN reg */
149
+#define GEM_MODID (0x000000FC / 4) /* Module ID reg */
150
+#define GEM_OCTTXLO (0x00000100 / 4) /* Octects transmitted Low reg */
151
+#define GEM_OCTTXHI (0x00000104 / 4) /* Octects transmitted High reg */
152
+#define GEM_TXCNT (0x00000108 / 4) /* Error-free Frames transmitted */
153
+#define GEM_TXBCNT (0x0000010C / 4) /* Error-free Broadcast Frames */
154
+#define GEM_TXMCNT (0x00000110 / 4) /* Error-free Multicast Frame */
155
+#define GEM_TXPAUSECNT (0x00000114 / 4) /* Pause Frames Transmitted */
156
+#define GEM_TX64CNT (0x00000118 / 4) /* Error-free 64 TX */
157
+#define GEM_TX65CNT (0x0000011C / 4) /* Error-free 65-127 TX */
158
+#define GEM_TX128CNT (0x00000120 / 4) /* Error-free 128-255 TX */
159
+#define GEM_TX256CNT (0x00000124 / 4) /* Error-free 256-511 */
160
+#define GEM_TX512CNT (0x00000128 / 4) /* Error-free 512-1023 TX */
161
+#define GEM_TX1024CNT (0x0000012C / 4) /* Error-free 1024-1518 TX */
162
+#define GEM_TX1519CNT (0x00000130 / 4) /* Error-free larger than 1519 TX */
163
+#define GEM_TXURUNCNT (0x00000134 / 4) /* TX under run error counter */
164
+#define GEM_SINGLECOLLCNT (0x00000138 / 4) /* Single Collision Frames */
165
+#define GEM_MULTCOLLCNT (0x0000013C / 4) /* Multiple Collision Frames */
166
+#define GEM_EXCESSCOLLCNT (0x00000140 / 4) /* Excessive Collision Frames */
167
+#define GEM_LATECOLLCNT (0x00000144 / 4) /* Late Collision Frames */
168
+#define GEM_DEFERTXCNT (0x00000148 / 4) /* Deferred Transmission Frames */
169
+#define GEM_CSENSECNT (0x0000014C / 4) /* Carrier Sense Error Counter */
170
+#define GEM_OCTRXLO (0x00000150 / 4) /* Octects Received register Low */
171
+#define GEM_OCTRXHI (0x00000154 / 4) /* Octects Received register High */
172
+#define GEM_RXCNT (0x00000158 / 4) /* Error-free Frames Received */
173
+#define GEM_RXBROADCNT (0x0000015C / 4) /* Error-free Broadcast Frames RX */
174
+#define GEM_RXMULTICNT (0x00000160 / 4) /* Error-free Multicast Frames RX */
175
+#define GEM_RXPAUSECNT (0x00000164 / 4) /* Pause Frames Received Counter */
176
+#define GEM_RX64CNT (0x00000168 / 4) /* Error-free 64 byte Frames RX */
177
+#define GEM_RX65CNT (0x0000016C / 4) /* Error-free 65-127B Frames RX */
178
+#define GEM_RX128CNT (0x00000170 / 4) /* Error-free 128-255B Frames RX */
179
+#define GEM_RX256CNT (0x00000174 / 4) /* Error-free 256-512B Frames RX */
180
+#define GEM_RX512CNT (0x00000178 / 4) /* Error-free 512-1023B Frames RX */
181
+#define GEM_RX1024CNT (0x0000017C / 4) /* Error-free 1024-1518B Frames RX */
182
+#define GEM_RX1519CNT (0x00000180 / 4) /* Error-free 1519-max Frames RX */
183
+#define GEM_RXUNDERCNT (0x00000184 / 4) /* Undersize Frames Received */
184
+#define GEM_RXOVERCNT (0x00000188 / 4) /* Oversize Frames Received */
185
+#define GEM_RXJABCNT (0x0000018C / 4) /* Jabbers Received Counter */
186
+#define GEM_RXFCSCNT (0x00000190 / 4) /* Frame Check seq. Error Counter */
187
+#define GEM_RXLENERRCNT (0x00000194 / 4) /* Length Field Error Counter */
188
+#define GEM_RXSYMERRCNT (0x00000198 / 4) /* Symbol Error Counter */
189
+#define GEM_RXALIGNERRCNT (0x0000019C / 4) /* Alignment Error Counter */
190
+#define GEM_RXRSCERRCNT (0x000001A0 / 4) /* Receive Resource Error Counter */
191
+#define GEM_RXORUNCNT (0x000001A4 / 4) /* Receive Overrun Counter */
192
+#define GEM_RXIPCSERRCNT (0x000001A8 / 4) /* IP header Checksum Err Counter */
193
+#define GEM_RXTCPCCNT (0x000001AC / 4) /* TCP Checksum Error Counter */
194
+#define GEM_RXUDPCCNT (0x000001B0 / 4) /* UDP Checksum Error Counter */
195
+
196
+#define GEM_1588S (0x000001D0 / 4) /* 1588 Timer Seconds */
197
+#define GEM_1588NS (0x000001D4 / 4) /* 1588 Timer Nanoseconds */
198
+#define GEM_1588ADJ (0x000001D8 / 4) /* 1588 Timer Adjust */
199
+#define GEM_1588INC (0x000001DC / 4) /* 1588 Timer Increment */
200
+#define GEM_PTPETXS (0x000001E0 / 4) /* PTP Event Frame Transmitted (s) */
201
+#define GEM_PTPETXNS (0x000001E4 / 4) /*
202
+ * PTP Event Frame Transmitted (ns)
203
+ */
204
+#define GEM_PTPERXS (0x000001E8 / 4) /* PTP Event Frame Received (s) */
205
+#define GEM_PTPERXNS (0x000001EC / 4) /* PTP Event Frame Received (ns) */
206
+#define GEM_PTPPTXS (0x000001E0 / 4) /* PTP Peer Frame Transmitted (s) */
207
+#define GEM_PTPPTXNS (0x000001E4 / 4) /* PTP Peer Frame Transmitted (ns) */
208
+#define GEM_PTPPRXS (0x000001E8 / 4) /* PTP Peer Frame Received (s) */
209
+#define GEM_PTPPRXNS (0x000001EC / 4) /* PTP Peer Frame Received (ns) */
210
211
/* Design Configuration Registers */
212
-#define GEM_DESCONF (0x00000280/4)
213
-#define GEM_DESCONF2 (0x00000284/4)
214
-#define GEM_DESCONF3 (0x00000288/4)
215
-#define GEM_DESCONF4 (0x0000028C/4)
216
-#define GEM_DESCONF5 (0x00000290/4)
217
-#define GEM_DESCONF6 (0x00000294/4)
218
+#define GEM_DESCONF (0x00000280 / 4)
219
+#define GEM_DESCONF2 (0x00000284 / 4)
220
+#define GEM_DESCONF3 (0x00000288 / 4)
221
+#define GEM_DESCONF4 (0x0000028C / 4)
222
+#define GEM_DESCONF5 (0x00000290 / 4)
223
+#define GEM_DESCONF6 (0x00000294 / 4)
224
#define GEM_DESCONF6_64B_MASK (1U << 23)
225
-#define GEM_DESCONF7 (0x00000298/4)
226
+#define GEM_DESCONF7 (0x00000298 / 4)
227
228
#define GEM_INT_Q1_STATUS (0x00000400 / 4)
229
#define GEM_INT_Q1_MASK (0x00000640 / 4)
230
--
231
2.5.0
232
233
diff view generated by jsdifflib
New patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
1
2
3
Add a property "jumbo-max-len", which sets default value of jumbo frames
4
up to 16,383 bytes. Add Frame length checks for standard and jumbo
5
frames.
6
7
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
11
hw/net/cadence_gem.c | 51 +++++++++++++++++++++++++++++++++++++++-----
12
include/hw/net/cadence_gem.h | 4 +++-
13
2 files changed, 49 insertions(+), 6 deletions(-)
14
15
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/net/cadence_gem.c
18
+++ b/hw/net/cadence_gem.c
19
@@ -XXX,XX +XXX,XX @@
20
#define GEM_TXPAUSE (0x0000003C / 4) /* TX Pause Time reg */
21
#define GEM_TXPARTIALSF (0x00000040 / 4) /* TX Partial Store and Forward */
22
#define GEM_RXPARTIALSF (0x00000044 / 4) /* RX Partial Store and Forward */
23
+#define GEM_JUMBO_MAX_LEN (0x00000048 / 4) /* Max Jumbo Frame Size */
24
#define GEM_HASHLO (0x00000080 / 4) /* Hash Low address reg */
25
#define GEM_HASHHI (0x00000084 / 4) /* Hash High address reg */
26
#define GEM_SPADDR1LO (0x00000088 / 4) /* Specific addr 1 low reg */
27
@@ -XXX,XX +XXX,XX @@
28
#define GEM_NWCFG_LERR_DISC 0x00010000 /* Discard RX frames with len err */
29
#define GEM_NWCFG_BUFF_OFST_M 0x0000C000 /* Receive buffer offset mask */
30
#define GEM_NWCFG_BUFF_OFST_S 14 /* Receive buffer offset shift */
31
+#define GEM_NWCFG_RCV_1538 0x00000100 /* Receive 1538 bytes frame */
32
#define GEM_NWCFG_UCAST_HASH 0x00000080 /* accept unicast if hash match */
33
#define GEM_NWCFG_MCAST_HASH 0x00000040 /* accept multicast if hash match */
34
#define GEM_NWCFG_BCAST_REJ 0x00000020 /* Reject broadcast packets */
35
#define GEM_NWCFG_PROMISC 0x00000010 /* Accept all packets */
36
+#define GEM_NWCFG_JUMBO_FRAME 0x00000008 /* Jumbo Frames enable */
37
38
#define GEM_DMACFG_ADDR_64B (1U << 30)
39
#define GEM_DMACFG_TX_BD_EXT (1U << 29)
40
@@ -XXX,XX +XXX,XX @@
41
42
/* GEM_ISR GEM_IER GEM_IDR GEM_IMR */
43
#define GEM_INT_TXCMPL 0x00000080 /* Transmit Complete */
44
+#define GEM_INT_AMBA_ERR 0x00000040
45
#define GEM_INT_TXUSED 0x00000008
46
#define GEM_INT_RXUSED 0x00000004
47
#define GEM_INT_RXCMPL 0x00000002
48
@@ -XXX,XX +XXX,XX @@ static inline void rx_desc_set_sar(uint32_t *desc, int sar_idx)
49
/* The broadcast MAC address: 0xFFFFFFFFFFFF */
50
static const uint8_t broadcast_addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
51
52
+static uint32_t gem_get_max_buf_len(CadenceGEMState *s, bool tx)
53
+{
54
+ uint32_t size;
55
+ if (s->regs[GEM_NWCFG] & GEM_NWCFG_JUMBO_FRAME) {
56
+ size = s->regs[GEM_JUMBO_MAX_LEN];
57
+ if (size > s->jumbo_max_len) {
58
+ size = s->jumbo_max_len;
59
+ qemu_log_mask(LOG_GUEST_ERROR, "GEM_JUMBO_MAX_LEN reg cannot be"
60
+ " greater than 0x%" PRIx32 "\n", s->jumbo_max_len);
61
+ }
62
+ } else if (tx) {
63
+ size = 1518;
64
+ } else {
65
+ size = s->regs[GEM_NWCFG] & GEM_NWCFG_RCV_1538 ? 1538 : 1518;
66
+ }
67
+ return size;
68
+}
69
+
70
static void gem_set_isr(CadenceGEMState *s, int q, uint32_t flag)
71
{
72
if (q == 0) {
73
@@ -XXX,XX +XXX,XX @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
74
/* Find which queue we are targeting */
75
q = get_queue_from_screen(s, rxbuf_ptr, rxbufsize);
76
77
+ if (size > gem_get_max_buf_len(s, false)) {
78
+ qemu_log_mask(LOG_GUEST_ERROR, "rx frame too long\n");
79
+ gem_set_isr(s, q, GEM_INT_AMBA_ERR);
80
+ return -1;
81
+ }
82
+
83
while (bytes_to_copy) {
84
hwaddr desc_addr;
85
86
@@ -XXX,XX +XXX,XX @@ static void gem_transmit(CadenceGEMState *s)
87
break;
88
}
89
90
- if (tx_desc_get_length(desc) > MAX_FRAME_SIZE -
91
+ if (tx_desc_get_length(desc) > gem_get_max_buf_len(s, true) -
92
(p - s->tx_packet)) {
93
- DB_PRINT("TX descriptor @ 0x%" HWADDR_PRIx \
94
- " too large: size 0x%x space 0x%zx\n",
95
+ qemu_log_mask(LOG_GUEST_ERROR, "TX descriptor @ 0x%" \
96
+ HWADDR_PRIx " too large: size 0x%x space 0x%zx\n",
97
packet_desc_addr, tx_desc_get_length(desc),
98
- MAX_FRAME_SIZE - (p - s->tx_packet));
99
+ gem_get_max_buf_len(s, true) - (p - s->tx_packet));
100
+ gem_set_isr(s, q, GEM_INT_AMBA_ERR);
101
break;
102
}
103
104
@@ -XXX,XX +XXX,XX @@ static void gem_reset(DeviceState *d)
105
s->regs[GEM_RXPARTIALSF] = 0x000003ff;
106
s->regs[GEM_MODID] = s->revision;
107
s->regs[GEM_DESCONF] = 0x02500111;
108
- s->regs[GEM_DESCONF2] = 0x2ab13fff;
109
+ s->regs[GEM_DESCONF2] = 0x2ab10000 | s->jumbo_max_len;
110
s->regs[GEM_DESCONF5] = 0x002f2045;
111
s->regs[GEM_DESCONF6] = GEM_DESCONF6_64B_MASK;
112
+ s->regs[GEM_JUMBO_MAX_LEN] = s->jumbo_max_len;
113
114
if (s->num_priority_queues > 1) {
115
queues_mask = MAKE_64BIT_MASK(1, s->num_priority_queues - 1);
116
@@ -XXX,XX +XXX,XX @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
117
s->regs[GEM_IMR] &= ~val;
118
gem_update_int_status(s);
119
break;
120
+ case GEM_JUMBO_MAX_LEN:
121
+ s->regs[GEM_JUMBO_MAX_LEN] = val & MAX_JUMBO_FRAME_SIZE_MASK;
122
+ break;
123
case GEM_INT_Q1_ENABLE ... GEM_INT_Q7_ENABLE:
124
s->regs[GEM_INT_Q1_MASK + offset - GEM_INT_Q1_ENABLE] &= ~val;
125
gem_update_int_status(s);
126
@@ -XXX,XX +XXX,XX @@ static void gem_realize(DeviceState *dev, Error **errp)
127
128
s->nic = qemu_new_nic(&net_gem_info, &s->conf,
129
object_get_typename(OBJECT(dev)), dev->id, s);
130
+
131
+ if (s->jumbo_max_len > MAX_FRAME_SIZE) {
132
+ error_setg(errp, "jumbo-max-len is greater than %d",
133
+ MAX_FRAME_SIZE);
134
+ return;
135
+ }
136
}
137
138
static void gem_init(Object *obj)
139
@@ -XXX,XX +XXX,XX @@ static Property gem_properties[] = {
140
num_type1_screeners, 4),
141
DEFINE_PROP_UINT8("num-type2-screeners", CadenceGEMState,
142
num_type2_screeners, 4),
143
+ DEFINE_PROP_UINT16("jumbo-max-len", CadenceGEMState,
144
+ jumbo_max_len, 10240),
145
DEFINE_PROP_END_OF_LIST(),
146
};
147
148
diff --git a/include/hw/net/cadence_gem.h b/include/hw/net/cadence_gem.h
149
index XXXXXXX..XXXXXXX 100644
150
--- a/include/hw/net/cadence_gem.h
151
+++ b/include/hw/net/cadence_gem.h
152
@@ -XXX,XX +XXX,XX @@
153
#define MAX_TYPE1_SCREENERS 16
154
#define MAX_TYPE2_SCREENERS 16
155
156
-#define MAX_FRAME_SIZE 2048
157
+#define MAX_JUMBO_FRAME_SIZE_MASK 0x3FFF
158
+#define MAX_FRAME_SIZE MAX_JUMBO_FRAME_SIZE_MASK
159
160
typedef struct CadenceGEMState {
161
/*< private >*/
162
@@ -XXX,XX +XXX,XX @@ typedef struct CadenceGEMState {
163
uint8_t num_type1_screeners;
164
uint8_t num_type2_screeners;
165
uint32_t revision;
166
+ uint16_t jumbo_max_len;
167
168
/* GEM registers backing store */
169
uint32_t regs[CADENCE_GEM_MAXREG];
170
--
171
2.5.0
172
173
diff view generated by jsdifflib
New patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
1
2
3
Advertise support of clear-on-read for ISR registers.
4
5
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
9
hw/net/cadence_gem.c | 2 +-
10
1 file changed, 1 insertion(+), 1 deletion(-)
11
12
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/net/cadence_gem.c
15
+++ b/hw/net/cadence_gem.c
16
@@ -XXX,XX +XXX,XX @@ static void gem_reset(DeviceState *d)
17
s->regs[GEM_TXPARTIALSF] = 0x000003ff;
18
s->regs[GEM_RXPARTIALSF] = 0x000003ff;
19
s->regs[GEM_MODID] = s->revision;
20
- s->regs[GEM_DESCONF] = 0x02500111;
21
+ s->regs[GEM_DESCONF] = 0x02D00111;
22
s->regs[GEM_DESCONF2] = 0x2ab10000 | s->jumbo_max_len;
23
s->regs[GEM_DESCONF5] = 0x002f2045;
24
s->regs[GEM_DESCONF6] = GEM_DESCONF6_64B_MASK;
25
--
26
2.5.0
27
28
diff view generated by jsdifflib
New patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
1
2
3
Mask all interrupt on reset.
4
5
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
9
hw/net/cadence_gem.c | 1 +
10
1 file changed, 1 insertion(+)
11
12
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/net/cadence_gem.c
15
+++ b/hw/net/cadence_gem.c
16
@@ -XXX,XX +XXX,XX @@ static void gem_reset(DeviceState *d)
17
s->regs[GEM_DESCONF2] = 0x2ab10000 | s->jumbo_max_len;
18
s->regs[GEM_DESCONF5] = 0x002f2045;
19
s->regs[GEM_DESCONF6] = GEM_DESCONF6_64B_MASK;
20
+ s->regs[GEM_INT_Q1_MASK] = 0x00000CE6;
21
s->regs[GEM_JUMBO_MAX_LEN] = s->jumbo_max_len;
22
23
if (s->num_priority_queues > 1) {
24
--
25
2.5.0
26
27
diff view generated by jsdifflib
New patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
1
2
3
TX_LAST bit should not be set by hardware, its set by guest to inform
4
the last bd of the frame.
5
6
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
7
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
11
hw/net/cadence_gem.c | 6 ------
12
1 file changed, 6 deletions(-)
13
14
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/net/cadence_gem.c
17
+++ b/hw/net/cadence_gem.c
18
@@ -XXX,XX +XXX,XX @@ static inline unsigned tx_desc_get_last(uint32_t *desc)
19
return (desc[1] & DESC_1_TX_LAST) ? 1 : 0;
20
}
21
22
-static inline void tx_desc_set_last(uint32_t *desc)
23
-{
24
- desc[1] |= DESC_1_TX_LAST;
25
-}
26
-
27
static inline unsigned tx_desc_get_length(uint32_t *desc)
28
{
29
return desc[1] & DESC_1_LENGTH;
30
@@ -XXX,XX +XXX,XX @@ static void gem_transmit(CadenceGEMState *s)
31
32
/* read next descriptor */
33
if (tx_desc_get_wrap(desc)) {
34
- tx_desc_set_last(desc);
35
36
if (s->regs[GEM_DMACFG] & GEM_DMACFG_ADDR_64B) {
37
packet_desc_addr = s->regs[GEM_TBQPH];
38
--
39
2.5.0
40
41
diff view generated by jsdifflib
New patch
1
From: Tong Ho <tong.ho@xilinx.com>
1
2
3
Two defects are fixed:
4
5
1/ Detection of multicast frames
6
2/ Treating drop of mis-addressed frames as non-error
7
8
Signed-off-by: Tong Ho <tong.ho@xilinx.com>
9
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
10
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
11
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
---
14
hw/net/cadence_gem.c | 26 +++++++++++---------------
15
1 file changed, 11 insertions(+), 15 deletions(-)
16
17
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/net/cadence_gem.c
20
+++ b/hw/net/cadence_gem.c
21
@@ -XXX,XX +XXX,XX @@
22
#include "qemu/module.h"
23
#include "sysemu/dma.h"
24
#include "net/checksum.h"
25
+#include "net/eth.h"
26
27
#define CADENCE_GEM_ERR_DEBUG 0
28
#define DB_PRINT(...) do {\
29
@@ -XXX,XX +XXX,XX @@ static unsigned calc_mac_hash(const uint8_t *mac)
30
static int gem_mac_address_filter(CadenceGEMState *s, const uint8_t *packet)
31
{
32
uint8_t *gem_spaddr;
33
- int i;
34
+ int i, is_mc;
35
36
/* Promiscuous mode? */
37
if (s->regs[GEM_NWCFG] & GEM_NWCFG_PROMISC) {
38
@@ -XXX,XX +XXX,XX @@ static int gem_mac_address_filter(CadenceGEMState *s, const uint8_t *packet)
39
}
40
41
/* Accept packets -w- hash match? */
42
- if ((packet[0] == 0x01 && (s->regs[GEM_NWCFG] & GEM_NWCFG_MCAST_HASH)) ||
43
- (packet[0] != 0x01 && (s->regs[GEM_NWCFG] & GEM_NWCFG_UCAST_HASH))) {
44
+ is_mc = is_multicast_ether_addr(packet);
45
+ if ((is_mc && (s->regs[GEM_NWCFG] & GEM_NWCFG_MCAST_HASH)) ||
46
+ (!is_mc && (s->regs[GEM_NWCFG] & GEM_NWCFG_UCAST_HASH))) {
47
+ uint64_t buckets;
48
unsigned hash_index;
49
50
hash_index = calc_mac_hash(packet);
51
- if (hash_index < 32) {
52
- if (s->regs[GEM_HASHLO] & (1<<hash_index)) {
53
- return packet[0] == 0x01 ? GEM_RX_MULTICAST_HASH_ACCEPT :
54
- GEM_RX_UNICAST_HASH_ACCEPT;
55
- }
56
- } else {
57
- hash_index -= 32;
58
- if (s->regs[GEM_HASHHI] & (1<<hash_index)) {
59
- return packet[0] == 0x01 ? GEM_RX_MULTICAST_HASH_ACCEPT :
60
- GEM_RX_UNICAST_HASH_ACCEPT;
61
- }
62
+ buckets = ((uint64_t)s->regs[GEM_HASHHI] << 32) | s->regs[GEM_HASHLO];
63
+ if ((buckets >> hash_index) & 1) {
64
+ return is_mc ? GEM_RX_MULTICAST_HASH_ACCEPT
65
+ : GEM_RX_UNICAST_HASH_ACCEPT;
66
}
67
}
68
69
@@ -XXX,XX +XXX,XX @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
70
/* Is this destination MAC address "for us" ? */
71
maf = gem_mac_address_filter(s, buf);
72
if (maf == GEM_RX_REJECT) {
73
- return -1;
74
+ return size; /* no, drop siliently b/c it's not an error */
75
}
76
77
/* Discard packets with receive length error enabled ? */
78
--
79
2.5.0
80
81
diff view generated by jsdifflib
New patch
1
The sender of packet will be checked in the qemu_net_queue_purge() but
2
we use NetClientState not its peer when trying to purge the incoming
3
queue in qemu_flush_or_purge_packets(). This will trigger the assert
4
in virtio_net_reset since we can't pass the sender check:
1
5
6
hw/net/virtio-net.c:533: void virtio_net_reset(VirtIODevice *): Assertion
7
`!virtio_net_get_subqueue(nc)->async_tx.elem' failed.
8
#9 0x55a33fa31b78 in virtio_net_reset hw/net/virtio-net.c:533:13
9
#10 0x55a33fc88412 in virtio_reset hw/virtio/virtio.c:1919:9
10
#11 0x55a341d82764 in virtio_bus_reset hw/virtio/virtio-bus.c:95:9
11
#12 0x55a341dba2de in virtio_pci_reset hw/virtio/virtio-pci.c:1824:5
12
#13 0x55a341db3e02 in virtio_pci_common_write hw/virtio/virtio-pci.c:1252:13
13
#14 0x55a33f62117b in memory_region_write_accessor memory.c:496:5
14
#15 0x55a33f6205e4 in access_with_adjusted_size memory.c:557:18
15
#16 0x55a33f61e177 in memory_region_dispatch_write memory.c:1488:16
16
17
Reproducer:
18
https://www.mail-archive.com/qemu-devel@nongnu.org/msg701914.html
19
20
Fix by using the peer.
21
22
Reported-by: "Alexander Bulekov" <alxndr@bu.edu>
23
Acked-by: Alexander Bulekov <alxndr@bu.edu>
24
Fixes: ca77d85e1dbf9 ("net: complete all queued packets on VM stop")
25
Cc: qemu-stable@nongnu.org
26
Signed-off-by: Jason Wang <jasowang@redhat.com>
27
---
28
net/net.c | 2 +-
29
1 file changed, 1 insertion(+), 1 deletion(-)
30
31
diff --git a/net/net.c b/net/net.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/net/net.c
34
+++ b/net/net.c
35
@@ -XXX,XX +XXX,XX @@ void qemu_flush_or_purge_queued_packets(NetClientState *nc, bool purge)
36
qemu_notify_event();
37
} else if (purge) {
38
/* Unable to empty the queue, purge remaining packets */
39
- qemu_net_queue_purge(nc->incoming_queue, nc);
40
+ qemu_net_queue_purge(nc->incoming_queue, nc->peer);
41
}
42
}
43
44
--
45
2.5.0
46
47
diff view generated by jsdifflib
New patch
1
From: Lukas Straub <lukasstraub2@web.de>
1
2
3
qemu_bh_new will set the bh to be executed in the main
4
loop. This causes crashes as colo_compare_handle_event assumes
5
that it has exclusive access the queues, which are also
6
concurrently accessed in the iothread.
7
8
Create the bh with the AioContext of the iothread to fulfill
9
these assumptions and fix the crashes. This is safe, because
10
the bh already takes the appropriate locks.
11
12
Signed-off-by: Lukas Straub <lukasstraub2@web.de>
13
Reviewed-by: Zhang Chen <chen.zhang@intel.com>
14
Reviewed-by: Derek Su <dereksu@qnap.com>
15
Tested-by: Derek Su <dereksu@qnap.com>
16
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
17
Signed-off-by: Jason Wang <jasowang@redhat.com>
18
---
19
net/colo-compare.c | 3 ++-
20
1 file changed, 2 insertions(+), 1 deletion(-)
21
22
diff --git a/net/colo-compare.c b/net/colo-compare.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/net/colo-compare.c
25
+++ b/net/colo-compare.c
26
@@ -XXX,XX +XXX,XX @@ static void colo_compare_handle_event(void *opaque)
27
28
static void colo_compare_iothread(CompareState *s)
29
{
30
+ AioContext *ctx = iothread_get_aio_context(s->iothread);
31
object_ref(OBJECT(s->iothread));
32
s->worker_context = iothread_get_g_main_context(s->iothread);
33
34
@@ -XXX,XX +XXX,XX @@ static void colo_compare_iothread(CompareState *s)
35
}
36
37
colo_compare_timer_init(s);
38
- s->event_bh = qemu_bh_new(colo_compare_handle_event, s);
39
+ s->event_bh = aio_bh_new(ctx, colo_compare_handle_event, s);
40
}
41
42
static char *compare_get_pri_indev(Object *obj, Error **errp)
43
--
44
2.5.0
45
46
diff view generated by jsdifflib
New patch
1
From: Lukas Straub <lukasstraub2@web.de>
1
2
3
To be able to convert compare_chr_send to a coroutine in the
4
next commit, use qemu_co_sleep_ns if in coroutine.
5
6
Signed-off-by: Lukas Straub <lukasstraub2@web.de>
7
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
8
Reviewed-by: Zhang Chen <chen.zhang@intel.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
13
chardev/char.c | 7 ++++++-
14
1 file changed, 6 insertions(+), 1 deletion(-)
15
16
diff --git a/chardev/char.c b/chardev/char.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/chardev/char.c
19
+++ b/chardev/char.c
20
@@ -XXX,XX +XXX,XX @@
21
#include "qemu/module.h"
22
#include "qemu/option.h"
23
#include "qemu/id.h"
24
+#include "qemu/coroutine.h"
25
26
#include "chardev/char-mux.h"
27
28
@@ -XXX,XX +XXX,XX @@ static int qemu_chr_write_buffer(Chardev *s,
29
retry:
30
res = cc->chr_write(s, buf + *offset, len - *offset);
31
if (res < 0 && errno == EAGAIN && write_all) {
32
- g_usleep(100);
33
+ if (qemu_in_coroutine()) {
34
+ qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, 100000);
35
+ } else {
36
+ g_usleep(100);
37
+ }
38
goto retry;
39
}
40
41
--
42
2.5.0
43
44
diff view generated by jsdifflib
New patch
1
1
From: Lukas Straub <lukasstraub2@web.de>
2
3
The chr_out chardev is connected to a filter-redirector
4
running in the main loop. qemu_chr_fe_write_all might block
5
here in compare_chr_send if the (socket-)buffer is full.
6
If another filter-redirector in the main loop want's to
7
send data to chr_pri_in it might also block if the buffer
8
is full. This leads to a deadlock because both event loops
9
get blocked.
10
11
Fix this by converting compare_chr_send to a coroutine and
12
putting the packets in a send queue.
13
14
Signed-off-by: Lukas Straub <lukasstraub2@web.de>
15
Reviewed-by: Zhang Chen <chen.zhang@intel.com>
16
Tested-by: Zhang Chen <chen.zhang@intel.com>
17
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
18
Signed-off-by: Jason Wang <jasowang@redhat.com>
19
---
20
net/colo-compare.c | 193 ++++++++++++++++++++++++++++++++++++++++-------------
21
net/colo.c | 7 ++
22
net/colo.h | 1 +
23
3 files changed, 156 insertions(+), 45 deletions(-)
24
25
diff --git a/net/colo-compare.c b/net/colo-compare.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/net/colo-compare.c
28
+++ b/net/colo-compare.c
29
@@ -XXX,XX +XXX,XX @@
30
#include "migration/migration.h"
31
#include "util.h"
32
33
+#include "block/aio-wait.h"
34
+#include "qemu/coroutine.h"
35
+
36
#define TYPE_COLO_COMPARE "colo-compare"
37
#define COLO_COMPARE(obj) \
38
OBJECT_CHECK(CompareState, (obj), TYPE_COLO_COMPARE)
39
@@ -XXX,XX +XXX,XX @@ static int event_unhandled_count;
40
* |packet | |packet + |packet | |packet +
41
* +--------+ +--------+ +--------+ +--------+
42
*/
43
+
44
+typedef struct SendCo {
45
+ Coroutine *co;
46
+ struct CompareState *s;
47
+ CharBackend *chr;
48
+ GQueue send_list;
49
+ bool notify_remote_frame;
50
+ bool done;
51
+ int ret;
52
+} SendCo;
53
+
54
+typedef struct SendEntry {
55
+ uint32_t size;
56
+ uint32_t vnet_hdr_len;
57
+ uint8_t *buf;
58
+} SendEntry;
59
+
60
typedef struct CompareState {
61
Object parent;
62
63
@@ -XXX,XX +XXX,XX @@ typedef struct CompareState {
64
SocketReadState pri_rs;
65
SocketReadState sec_rs;
66
SocketReadState notify_rs;
67
+ SendCo out_sendco;
68
+ SendCo notify_sendco;
69
bool vnet_hdr;
70
uint32_t compare_timeout;
71
uint32_t expired_scan_cycle;
72
@@ -XXX,XX +XXX,XX @@ enum {
73
74
75
static int compare_chr_send(CompareState *s,
76
- const uint8_t *buf,
77
+ uint8_t *buf,
78
uint32_t size,
79
uint32_t vnet_hdr_len,
80
- bool notify_remote_frame);
81
+ bool notify_remote_frame,
82
+ bool zero_copy);
83
84
static bool packet_matches_str(const char *str,
85
const uint8_t *buf,
86
@@ -XXX,XX +XXX,XX @@ static void notify_remote_frame(CompareState *s)
87
char msg[] = "DO_CHECKPOINT";
88
int ret = 0;
89
90
- ret = compare_chr_send(s, (uint8_t *)msg, strlen(msg), 0, true);
91
+ ret = compare_chr_send(s, (uint8_t *)msg, strlen(msg), 0, true, false);
92
if (ret < 0) {
93
error_report("Notify Xen COLO-frame failed");
94
}
95
@@ -XXX,XX +XXX,XX @@ static void colo_release_primary_pkt(CompareState *s, Packet *pkt)
96
pkt->data,
97
pkt->size,
98
pkt->vnet_hdr_len,
99
- false);
100
+ false,
101
+ true);
102
if (ret < 0) {
103
error_report("colo send primary packet failed");
104
}
105
trace_colo_compare_main("packet same and release packet");
106
- packet_destroy(pkt, NULL);
107
+ packet_destroy_partial(pkt, NULL);
108
}
109
110
/*
111
@@ -XXX,XX +XXX,XX @@ static void colo_compare_connection(void *opaque, void *user_data)
112
}
113
}
114
115
-static int compare_chr_send(CompareState *s,
116
- const uint8_t *buf,
117
- uint32_t size,
118
- uint32_t vnet_hdr_len,
119
- bool notify_remote_frame)
120
+static void coroutine_fn _compare_chr_send(void *opaque)
121
{
122
+ SendCo *sendco = opaque;
123
+ CompareState *s = sendco->s;
124
int ret = 0;
125
- uint32_t len = htonl(size);
126
127
- if (!size) {
128
- return 0;
129
- }
130
+ while (!g_queue_is_empty(&sendco->send_list)) {
131
+ SendEntry *entry = g_queue_pop_tail(&sendco->send_list);
132
+ uint32_t len = htonl(entry->size);
133
134
- if (notify_remote_frame) {
135
- ret = qemu_chr_fe_write_all(&s->chr_notify_dev,
136
- (uint8_t *)&len,
137
- sizeof(len));
138
- } else {
139
- ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len));
140
- }
141
+ ret = qemu_chr_fe_write_all(sendco->chr, (uint8_t *)&len, sizeof(len));
142
143
- if (ret != sizeof(len)) {
144
- goto err;
145
- }
146
+ if (ret != sizeof(len)) {
147
+ g_free(entry->buf);
148
+ g_slice_free(SendEntry, entry);
149
+ goto err;
150
+ }
151
152
- if (s->vnet_hdr) {
153
- /*
154
- * We send vnet header len make other module(like filter-redirector)
155
- * know how to parse net packet correctly.
156
- */
157
- len = htonl(vnet_hdr_len);
158
+ if (!sendco->notify_remote_frame && s->vnet_hdr) {
159
+ /*
160
+ * We send vnet header len make other module(like filter-redirector)
161
+ * know how to parse net packet correctly.
162
+ */
163
+ len = htonl(entry->vnet_hdr_len);
164
165
- if (!notify_remote_frame) {
166
- ret = qemu_chr_fe_write_all(&s->chr_out,
167
+ ret = qemu_chr_fe_write_all(sendco->chr,
168
(uint8_t *)&len,
169
sizeof(len));
170
+
171
+ if (ret != sizeof(len)) {
172
+ g_free(entry->buf);
173
+ g_slice_free(SendEntry, entry);
174
+ goto err;
175
+ }
176
}
177
178
- if (ret != sizeof(len)) {
179
+ ret = qemu_chr_fe_write_all(sendco->chr,
180
+ (uint8_t *)entry->buf,
181
+ entry->size);
182
+
183
+ if (ret != entry->size) {
184
+ g_free(entry->buf);
185
+ g_slice_free(SendEntry, entry);
186
goto err;
187
}
188
+
189
+ g_free(entry->buf);
190
+ g_slice_free(SendEntry, entry);
191
}
192
193
+ sendco->ret = 0;
194
+ goto out;
195
+
196
+err:
197
+ while (!g_queue_is_empty(&sendco->send_list)) {
198
+ SendEntry *entry = g_queue_pop_tail(&sendco->send_list);
199
+ g_free(entry->buf);
200
+ g_slice_free(SendEntry, entry);
201
+ }
202
+ sendco->ret = ret < 0 ? ret : -EIO;
203
+out:
204
+ sendco->co = NULL;
205
+ sendco->done = true;
206
+ aio_wait_kick();
207
+}
208
+
209
+static int compare_chr_send(CompareState *s,
210
+ uint8_t *buf,
211
+ uint32_t size,
212
+ uint32_t vnet_hdr_len,
213
+ bool notify_remote_frame,
214
+ bool zero_copy)
215
+{
216
+ SendCo *sendco;
217
+ SendEntry *entry;
218
+
219
if (notify_remote_frame) {
220
- ret = qemu_chr_fe_write_all(&s->chr_notify_dev,
221
- (uint8_t *)buf,
222
- size);
223
+ sendco = &s->notify_sendco;
224
} else {
225
- ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)buf, size);
226
+ sendco = &s->out_sendco;
227
}
228
229
- if (ret != size) {
230
- goto err;
231
+ if (!size) {
232
+ return 0;
233
}
234
235
- return 0;
236
+ entry = g_slice_new(SendEntry);
237
+ entry->size = size;
238
+ entry->vnet_hdr_len = vnet_hdr_len;
239
+ if (zero_copy) {
240
+ entry->buf = buf;
241
+ } else {
242
+ entry->buf = g_malloc(size);
243
+ memcpy(entry->buf, buf, size);
244
+ }
245
+ g_queue_push_head(&sendco->send_list, entry);
246
+
247
+ if (sendco->done) {
248
+ sendco->co = qemu_coroutine_create(_compare_chr_send, sendco);
249
+ sendco->done = false;
250
+ qemu_coroutine_enter(sendco->co);
251
+ if (sendco->done) {
252
+ /* report early errors */
253
+ return sendco->ret;
254
+ }
255
+ }
256
257
-err:
258
- return ret < 0 ? ret : -EIO;
259
+ /* assume success */
260
+ return 0;
261
}
262
263
static int compare_chr_can_read(void *opaque)
264
@@ -XXX,XX +XXX,XX @@ static void compare_pri_rs_finalize(SocketReadState *pri_rs)
265
pri_rs->buf,
266
pri_rs->packet_len,
267
pri_rs->vnet_hdr_len,
268
+ false,
269
false);
270
} else {
271
/* compare packet in the specified connection */
272
@@ -XXX,XX +XXX,XX @@ static void compare_notify_rs_finalize(SocketReadState *notify_rs)
273
if (packet_matches_str("COLO_USERSPACE_PROXY_INIT",
274
notify_rs->buf,
275
notify_rs->packet_len)) {
276
- ret = compare_chr_send(s, (uint8_t *)msg, strlen(msg), 0, true);
277
+ ret = compare_chr_send(s, (uint8_t *)msg, strlen(msg), 0, true, false);
278
if (ret < 0) {
279
error_report("Notify Xen COLO-frame INIT failed");
280
}
281
@@ -XXX,XX +XXX,XX @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
282
283
QTAILQ_INSERT_TAIL(&net_compares, s, next);
284
285
+ s->out_sendco.s = s;
286
+ s->out_sendco.chr = &s->chr_out;
287
+ s->out_sendco.notify_remote_frame = false;
288
+ s->out_sendco.done = true;
289
+ g_queue_init(&s->out_sendco.send_list);
290
+
291
+ if (s->notify_dev) {
292
+ s->notify_sendco.s = s;
293
+ s->notify_sendco.chr = &s->chr_notify_dev;
294
+ s->notify_sendco.notify_remote_frame = true;
295
+ s->notify_sendco.done = true;
296
+ g_queue_init(&s->notify_sendco.send_list);
297
+ }
298
+
299
g_queue_init(&s->conn_list);
300
301
qemu_mutex_init(&event_mtx);
302
@@ -XXX,XX +XXX,XX @@ static void colo_flush_packets(void *opaque, void *user_data)
303
pkt->data,
304
pkt->size,
305
pkt->vnet_hdr_len,
306
- false);
307
- packet_destroy(pkt, NULL);
308
+ false,
309
+ true);
310
+ packet_destroy_partial(pkt, NULL);
311
}
312
while (!g_queue_is_empty(&conn->secondary_list)) {
313
pkt = g_queue_pop_head(&conn->secondary_list);
314
@@ -XXX,XX +XXX,XX @@ static void colo_compare_finalize(Object *obj)
315
}
316
}
317
318
+ AioContext *ctx = iothread_get_aio_context(s->iothread);
319
+ aio_context_acquire(ctx);
320
+ AIO_WAIT_WHILE(ctx, !s->out_sendco.done);
321
+ if (s->notify_dev) {
322
+ AIO_WAIT_WHILE(ctx, !s->notify_sendco.done);
323
+ }
324
+ aio_context_release(ctx);
325
+
326
/* Release all unhandled packets after compare thead exited */
327
g_queue_foreach(&s->conn_list, colo_flush_packets, s);
328
+ AIO_WAIT_WHILE(NULL, !s->out_sendco.done);
329
330
g_queue_clear(&s->conn_list);
331
+ g_queue_clear(&s->out_sendco.send_list);
332
+ if (s->notify_dev) {
333
+ g_queue_clear(&s->notify_sendco.send_list);
334
+ }
335
336
if (s->connection_track_table) {
337
g_hash_table_destroy(s->connection_track_table);
338
diff --git a/net/colo.c b/net/colo.c
339
index XXXXXXX..XXXXXXX 100644
340
--- a/net/colo.c
341
+++ b/net/colo.c
342
@@ -XXX,XX +XXX,XX @@ void packet_destroy(void *opaque, void *user_data)
343
g_slice_free(Packet, pkt);
344
}
345
346
+void packet_destroy_partial(void *opaque, void *user_data)
347
+{
348
+ Packet *pkt = opaque;
349
+
350
+ g_slice_free(Packet, pkt);
351
+}
352
+
353
/*
354
* Clear hashtable, stop this hash growing really huge
355
*/
356
diff --git a/net/colo.h b/net/colo.h
357
index XXXXXXX..XXXXXXX 100644
358
--- a/net/colo.h
359
+++ b/net/colo.h
360
@@ -XXX,XX +XXX,XX @@ bool connection_has_tracked(GHashTable *connection_track_table,
361
void connection_hashtable_reset(GHashTable *connection_track_table);
362
Packet *packet_new(const void *data, int size, int vnet_hdr_len);
363
void packet_destroy(void *opaque, void *user_data);
364
+void packet_destroy_partial(void *opaque, void *user_data);
365
366
#endif /* NET_COLO_H */
367
--
368
2.5.0
369
370
diff view generated by jsdifflib
New patch
1
From: Lukas Straub <lukasstraub2@web.de>
1
2
3
Else the log will be flooded if there is a lot of network
4
traffic.
5
6
Signed-off-by: Lukas Straub <lukasstraub2@web.de>
7
Reviewed-by: Zhang Chen <chen.zhang@intel.com>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
13
net/colo-compare.c | 10 ++++++----
14
1 file changed, 6 insertions(+), 4 deletions(-)
15
16
diff --git a/net/colo-compare.c b/net/colo-compare.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/net/colo-compare.c
19
+++ b/net/colo-compare.c
20
@@ -XXX,XX +XXX,XX @@ sec:
21
g_queue_push_head(&conn->primary_list, ppkt);
22
g_queue_push_head(&conn->secondary_list, spkt);
23
24
- qemu_hexdump((char *)ppkt->data, stderr,
25
- "colo-compare ppkt", ppkt->size);
26
- qemu_hexdump((char *)spkt->data, stderr,
27
- "colo-compare spkt", spkt->size);
28
+ if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) {
29
+ qemu_hexdump((char *)ppkt->data, stderr,
30
+ "colo-compare ppkt", ppkt->size);
31
+ qemu_hexdump((char *)spkt->data, stderr,
32
+ "colo-compare spkt", spkt->size);
33
+ }
34
35
colo_compare_inconsistency_notify(s);
36
}
37
--
38
2.5.0
39
40
diff view generated by jsdifflib
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
1
From: Lukas Straub <lukasstraub2@web.de>
2
2
3
Modified the function colo_packet_compare_common to prepare for the
3
If the colo-compare object is removed before failover and a
4
tcp packet comparison in the next patch.
4
checkpoint happens, qemu crashes because it tries to lock
5
the destroyed event_mtx in colo_notify_compares_event.
5
6
6
Cc: Zhang Chen <zhangckid@gmail.com>
7
Fix this by checking if everything is initialized by
7
Cc: Li Zhijian <lizhijian@cn.fujitsu.com>
8
introducing a new variable colo_compare_active which
8
Cc: Jason Wang <jasowang@redhat.com>
9
is protected by a new mutex colo_compare_mutex. The new mutex
10
also protects against concurrent access of the net_compares
11
list and makes sure that colo_notify_compares_event isn't
12
active while we destroy event_mtx and event_complete_cond.
9
13
10
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
14
With this it also is again possible to use colo without
11
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
15
colo-compare (periodic mode) and to use multiple colo-compare
12
Signed-off-by: Zhang Chen <zhangckid@gmail.com>
16
for multiple network interfaces.
13
Reviewed-by: Zhang Chen <zhangckid@gmail.com>
17
18
Signed-off-by: Lukas Straub <lukasstraub2@web.de>
19
Tested-by: Lukas Straub <lukasstraub2@web.de>
20
Reviewed-by: Zhang Chen <chen.zhang@intel.com>
21
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
14
Signed-off-by: Jason Wang <jasowang@redhat.com>
22
Signed-off-by: Jason Wang <jasowang@redhat.com>
15
---
23
---
16
net/colo-compare.c | 88 +++++++++++++++++++++++++++---------------------------
24
net/colo-compare.c | 35 +++++++++++++++++++++++++++++------
17
1 file changed, 44 insertions(+), 44 deletions(-)
25
1 file changed, 29 insertions(+), 6 deletions(-)
18
26
19
diff --git a/net/colo-compare.c b/net/colo-compare.c
27
diff --git a/net/colo-compare.c b/net/colo-compare.c
20
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
21
--- a/net/colo-compare.c
29
--- a/net/colo-compare.c
22
+++ b/net/colo-compare.c
30
+++ b/net/colo-compare.c
23
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode, Connection **con)
31
@@ -XXX,XX +XXX,XX @@ static NotifierList colo_compare_notifiers =
24
* return: 0 means packet same
32
#define REGULAR_PACKET_CHECK_MS 3000
25
* > 0 || < 0 means packet different
33
#define DEFAULT_TIME_OUT_MS 3000
26
*/
34
27
-static int colo_packet_compare_common(Packet *ppkt,
35
+static QemuMutex colo_compare_mutex;
28
- Packet *spkt,
36
+static bool colo_compare_active;
29
- int poffset,
37
static QemuMutex event_mtx;
30
- int soffset)
38
static QemuCond event_complete_cond;
31
+static int colo_compare_packet_payload(Packet *ppkt,
39
static int event_unhandled_count;
32
+ Packet *spkt,
40
@@ -XXX,XX +XXX,XX @@ static void check_old_packet_regular(void *opaque)
33
+ uint16_t poffset,
41
void colo_notify_compares_event(void *opaque, int event, Error **errp)
34
+ uint16_t soffset,
42
{
35
+ uint16_t len)
43
CompareState *s;
44
+ qemu_mutex_lock(&colo_compare_mutex);
36
+
45
+
37
{
46
+ if (!colo_compare_active) {
38
if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) {
47
+ qemu_mutex_unlock(&colo_compare_mutex);
39
char pri_ip_src[20], pri_ip_dst[20], sec_ip_src[20], sec_ip_dst[20];
48
+ return;
40
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_common(Packet *ppkt,
49
+ }
41
sec_ip_src, sec_ip_dst);
50
51
qemu_mutex_lock(&event_mtx);
52
QTAILQ_FOREACH(s, &net_compares, next) {
53
@@ -XXX,XX +XXX,XX @@ void colo_notify_compares_event(void *opaque, int event, Error **errp)
42
}
54
}
43
55
44
- poffset = ppkt->vnet_hdr_len + poffset;
56
qemu_mutex_unlock(&event_mtx);
45
- soffset = ppkt->vnet_hdr_len + soffset;
57
+ qemu_mutex_unlock(&colo_compare_mutex);
58
}
59
60
static void colo_compare_timer_init(CompareState *s)
61
@@ -XXX,XX +XXX,XX @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
62
s->vnet_hdr);
63
}
64
65
+ qemu_mutex_lock(&colo_compare_mutex);
66
+ if (!colo_compare_active) {
67
+ qemu_mutex_init(&event_mtx);
68
+ qemu_cond_init(&event_complete_cond);
69
+ colo_compare_active = true;
70
+ }
71
QTAILQ_INSERT_TAIL(&net_compares, s, next);
72
+ qemu_mutex_unlock(&colo_compare_mutex);
73
74
s->out_sendco.s = s;
75
s->out_sendco.chr = &s->chr_out;
76
@@ -XXX,XX +XXX,XX @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
77
78
g_queue_init(&s->conn_list);
79
80
- qemu_mutex_init(&event_mtx);
81
- qemu_cond_init(&event_complete_cond);
46
-
82
-
47
- if (ppkt->size - poffset == spkt->size - soffset) {
83
s->connection_track_table = g_hash_table_new_full(connection_key_hash,
48
- return memcmp(ppkt->data + poffset,
84
connection_key_equal,
49
- spkt->data + soffset,
85
g_free,
50
- spkt->size - soffset);
86
@@ -XXX,XX +XXX,XX @@ static void colo_compare_finalize(Object *obj)
51
- } else {
87
52
- trace_colo_compare_main("Net packet size are not the same");
88
qemu_bh_delete(s->event_bh);
53
- return -1;
89
54
- }
90
+ qemu_mutex_lock(&colo_compare_mutex);
55
+ return memcmp(ppkt->data + poffset, spkt->data + soffset, len);
91
QTAILQ_FOREACH(tmp, &net_compares, next) {
92
if (tmp == s) {
93
QTAILQ_REMOVE(&net_compares, s, next);
94
break;
95
}
96
}
97
+ if (QTAILQ_EMPTY(&net_compares)) {
98
+ colo_compare_active = false;
99
+ qemu_mutex_destroy(&event_mtx);
100
+ qemu_cond_destroy(&event_complete_cond);
101
+ }
102
+ qemu_mutex_unlock(&colo_compare_mutex);
103
104
AioContext *ctx = iothread_get_aio_context(s->iothread);
105
aio_context_acquire(ctx);
106
@@ -XXX,XX +XXX,XX @@ static void colo_compare_finalize(Object *obj)
107
object_unref(OBJECT(s->iothread));
108
}
109
110
- qemu_mutex_destroy(&event_mtx);
111
- qemu_cond_destroy(&event_complete_cond);
112
-
113
g_free(s->pri_indev);
114
g_free(s->sec_indev);
115
g_free(s->outdev);
116
g_free(s->notify_dev);
56
}
117
}
57
118
58
/*
119
+static void __attribute__((__constructor__)) colo_compare_init_globals(void)
59
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_tcp(Packet *spkt, Packet *ppkt)
120
+{
60
* the secondary guest's timestamp. COLO just focus on payload,
121
+ colo_compare_active = false;
61
* so we just need skip this field.
122
+ qemu_mutex_init(&colo_compare_mutex);
62
*/
123
+}
63
- if (ptcp->th_off > 5) {
64
- ptrdiff_t ptcp_offset, stcp_offset;
65
66
- ptcp_offset = ppkt->transport_header - (uint8_t *)ppkt->data
67
- + (ptcp->th_off * 4) - ppkt->vnet_hdr_len;
68
- stcp_offset = spkt->transport_header - (uint8_t *)spkt->data
69
- + (stcp->th_off * 4) - spkt->vnet_hdr_len;
70
+ ptrdiff_t ptcp_offset, stcp_offset;
71
72
- /*
73
- * When network is busy, some tcp options(like sack) will unpredictable
74
- * occur in primary side or secondary side. it will make packet size
75
- * not same, but the two packet's payload is identical. colo just
76
- * care about packet payload, so we skip the option field.
77
- */
78
- res = colo_packet_compare_common(ppkt, spkt, ptcp_offset, stcp_offset);
79
- } else if (ptcp->th_sum == stcp->th_sum) {
80
- res = colo_packet_compare_common(ppkt, spkt, ETH_HLEN, ETH_HLEN);
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;
133
}
134
135
/*
136
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt)
137
*/
138
static int colo_packet_compare_icmp(Packet *spkt, Packet *ppkt)
139
{
140
- int network_header_length = ppkt->ip->ip_hl * 4;
141
+ uint16_t network_header_length = ppkt->ip->ip_hl << 2;
142
+ uint16_t offset = network_header_length + ETH_HLEN + ppkt->vnet_hdr_len;
143
144
trace_colo_compare_main("compare icmp");
145
146
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_icmp(Packet *spkt, Packet *ppkt)
147
* other field like TOS,TTL,IP Checksum. we only need to compare
148
* the ip payload here.
149
*/
150
- if (colo_packet_compare_common(ppkt, spkt,
151
- network_header_length + ETH_HLEN,
152
- network_header_length + ETH_HLEN)) {
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
+
124
+
168
trace_colo_compare_main("compare other");
125
static const TypeInfo colo_compare_info = {
169
if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) {
126
.name = TYPE_COLO_COMPARE,
170
char pri_ip_src[20], pri_ip_dst[20], sec_ip_src[20], sec_ip_dst[20];
127
.parent = TYPE_OBJECT,
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);
182
}
183
184
static int colo_old_packet_check_one(Packet *pkt, int64_t *check_time)
185
--
128
--
186
2.7.4
129
2.5.0
187
130
188
131
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Lukas Straub <lukasstraub2@web.de>
2
2
3
It does not make much sense to limit these commands to the legacy 'vlan'
3
In colo_compare_complete, insert CompareState into net_compares
4
concept only, they should work with the modern netdevs, too. So now
4
only after everything has been initialized.
5
it is possible to use this command with one, two or three parameters.
5
In colo_compare_finalize, remove CompareState from net_compares
6
before anything is deinitialized.
6
7
7
With one parameter, the command installs a hostfwd rule on the default
8
Signed-off-by: Lukas Straub <lukasstraub2@web.de>
8
"user" network:
9
Reviewed-by: Zhang Chen <chen.zhang@intel.com>
9
hostfwd_add tcp:...
10
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
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.
19
20
Signed-off-by: Thomas Huth <thuth@redhat.com>
21
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
22
---
12
---
23
hmp-commands.hx | 4 ++--
13
net/colo-compare.c | 45 +++++++++++++++++++++++----------------------
24
net/slirp.c | 33 +++++++++++++++++++++++----------
14
1 file changed, 23 insertions(+), 22 deletions(-)
25
2 files changed, 25 insertions(+), 12 deletions(-)
26
15
27
diff --git a/hmp-commands.hx b/hmp-commands.hx
16
diff --git a/net/colo-compare.c b/net/colo-compare.c
28
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
29
--- a/hmp-commands.hx
18
--- a/net/colo-compare.c
30
+++ b/hmp-commands.hx
19
+++ b/net/colo-compare.c
31
@@ -XXX,XX +XXX,XX @@ ETEXI
20
@@ -XXX,XX +XXX,XX @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
32
{
21
s->vnet_hdr);
33
.name = "hostfwd_add",
22
}
34
.args_type = "arg1:s,arg2:s?,arg3:s?",
23
35
- .params = "[vlan_id name] [tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport",
24
- qemu_mutex_lock(&colo_compare_mutex);
36
+ .params = "[hub_id name]|[netdev_id] [tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport",
25
- if (!colo_compare_active) {
37
.help = "redirect TCP or UDP connections from host to guest (requires -net user)",
26
- qemu_mutex_init(&event_mtx);
38
.cmd = hmp_hostfwd_add,
27
- qemu_cond_init(&event_complete_cond);
39
},
28
- colo_compare_active = true;
40
@@ -XXX,XX +XXX,XX @@ ETEXI
29
- }
41
{
30
- QTAILQ_INSERT_TAIL(&net_compares, s, next);
42
.name = "hostfwd_remove",
31
- qemu_mutex_unlock(&colo_compare_mutex);
43
.args_type = "arg1:s,arg2:s?,arg3:s?",
32
-
44
- .params = "[vlan_id name] [tcp|udp]:[hostaddr]:hostport",
33
s->out_sendco.s = s;
45
+ .params = "[hub_id name]|[netdev_id] [tcp|udp]:[hostaddr]:hostport",
34
s->out_sendco.chr = &s->chr_out;
46
.help = "remove host-to-guest TCP or UDP redirection",
35
s->out_sendco.notify_remote_frame = false;
47
.cmd = hmp_hostfwd_remove,
36
@@ -XXX,XX +XXX,XX @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
48
},
37
connection_destroy);
49
diff --git a/net/slirp.c b/net/slirp.c
38
50
index XXXXXXX..XXXXXXX 100644
39
colo_compare_iothread(s);
51
--- a/net/slirp.c
40
+
52
+++ b/net/slirp.c
41
+ qemu_mutex_lock(&colo_compare_mutex);
53
@@ -XXX,XX +XXX,XX @@ error:
42
+ if (!colo_compare_active) {
54
return -1;
43
+ qemu_mutex_init(&event_mtx);
44
+ qemu_cond_init(&event_complete_cond);
45
+ colo_compare_active = true;
46
+ }
47
+ QTAILQ_INSERT_TAIL(&net_compares, s, next);
48
+ qemu_mutex_unlock(&colo_compare_mutex);
49
+
50
return;
55
}
51
}
56
52
57
-static SlirpState *slirp_lookup(Monitor *mon, const char *vlan,
53
@@ -XXX,XX +XXX,XX @@ static void colo_compare_finalize(Object *obj)
58
- const char *stack)
54
CompareState *s = COLO_COMPARE(obj);
59
+static SlirpState *slirp_lookup(Monitor *mon, const char *hub_id,
55
CompareState *tmp = NULL;
60
+ const char *name)
56
61
{
57
- qemu_chr_fe_deinit(&s->chr_pri_in, false);
58
- qemu_chr_fe_deinit(&s->chr_sec_in, false);
59
- qemu_chr_fe_deinit(&s->chr_out, false);
60
- if (s->notify_dev) {
61
- qemu_chr_fe_deinit(&s->chr_notify_dev, false);
62
- }
62
-
63
-
63
- if (vlan) {
64
- if (s->iothread) {
64
+ if (name) {
65
- colo_compare_timer_del(s);
65
NetClientState *nc;
66
- }
66
- nc = net_hub_find_client_by_name(strtol(vlan, NULL, 0), stack);
67
-
67
- if (!nc) {
68
- qemu_bh_delete(s->event_bh);
68
- monitor_printf(mon, "unrecognized (vlan-id, stackname) pair\n");
69
-
69
- return NULL;
70
qemu_mutex_lock(&colo_compare_mutex);
70
+ if (hub_id) {
71
QTAILQ_FOREACH(tmp, &net_compares, next) {
71
+ nc = net_hub_find_client_by_name(strtol(hub_id, NULL, 0), name);
72
if (tmp == s) {
72
+ if (!nc) {
73
@@ -XXX,XX +XXX,XX @@ static void colo_compare_finalize(Object *obj)
73
+ monitor_printf(mon, "unrecognized (vlan-id, stackname) pair\n");
74
}
74
+ return NULL;
75
qemu_mutex_unlock(&colo_compare_mutex);
75
+ }
76
76
+ } else {
77
+ qemu_chr_fe_deinit(&s->chr_pri_in, false);
77
+ nc = qemu_find_netdev(name);
78
+ qemu_chr_fe_deinit(&s->chr_sec_in, false);
78
+ if (!nc) {
79
+ qemu_chr_fe_deinit(&s->chr_out, false);
79
+ monitor_printf(mon, "unrecognized netdev id '%s'\n", name);
80
+ if (s->notify_dev) {
80
+ return NULL;
81
+ qemu_chr_fe_deinit(&s->chr_notify_dev, false);
81
+ }
82
+ }
82
}
83
+
83
if (strcmp(nc->model, "user")) {
84
+ if (s->iothread) {
84
monitor_printf(mon, "invalid device specified\n");
85
+ colo_compare_timer_del(s);
85
@@ -XXX,XX +XXX,XX @@ void hmp_hostfwd_remove(Monitor *mon, const QDict *qdict)
86
+ }
86
const char *arg2 = qdict_get_try_str(qdict, "arg2");
87
+
87
const char *arg3 = qdict_get_try_str(qdict, "arg3");
88
+ qemu_bh_delete(s->event_bh);
88
89
+
89
- if (arg2) {
90
AioContext *ctx = iothread_get_aio_context(s->iothread);
90
+ if (arg3) {
91
aio_context_acquire(ctx);
91
s = slirp_lookup(mon, arg1, arg2);
92
AIO_WAIT_WHILE(ctx, !s->out_sendco.done);
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;
113
--
93
--
114
2.7.4
94
2.5.0
115
95
116
96
diff view generated by jsdifflib
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
1
From: Derek Su <dereksu@qnap.com>
2
2
3
Packet size some time different or when network is busy.
3
The patch is to fix the "pkt" memory leak in packet_enqueue().
4
Based on same payload size, but TCP protocol can not
4
The allocated "pkt" needs to be freed if the colo compare
5
guarantee send the same one packet in the same way,
5
primary or secondary queue is too big.
6
6
7
like that:
7
Replace the error_report of full queue with a trace event.
8
We send this payload:
9
------------------------------
10
| header |1|2|3|4|5|6|7|8|9|0|
11
------------------------------
12
8
13
primary:
9
Signed-off-by: Derek Su <dereksu@qnap.com>
14
ppkt1:
10
Reviewed-by: Zhang Chen <chen.zhang@intel.com>
15
----------------
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
16
| header |1|2|3|
12
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
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
60
Cc: Zhang Chen <zhangckid@gmail.com>
61
Cc: Li Zhijian <lizhijian@cn.fujitsu.com>
62
Cc: Jason Wang <jasowang@redhat.com>
63
64
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.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>
69
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
Signed-off-by: Jason Wang <jasowang@redhat.com>
70
---
14
---
71
net/colo-compare.c | 343 +++++++++++++++++++++++++++++++++++------------------
15
net/colo-compare.c | 23 +++++++++++++++--------
72
net/colo.c | 9 ++
16
net/trace-events | 1 +
73
net/colo.h | 15 +++
17
2 files changed, 16 insertions(+), 8 deletions(-)
74
net/trace-events | 2 +-
75
4 files changed, 250 insertions(+), 119 deletions(-)
76
18
77
diff --git a/net/colo-compare.c b/net/colo-compare.c
19
diff --git a/net/colo-compare.c b/net/colo-compare.c
78
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
79
--- a/net/colo-compare.c
21
--- a/net/colo-compare.c
80
+++ b/net/colo-compare.c
22
+++ b/net/colo-compare.c
81
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@ enum {
82
#define COMPARE_READ_LEN_MAX NET_BUFSIZE
24
SECONDARY_IN,
83
#define MAX_QUEUE_SIZE 1024
25
};
84
26
85
+#define COLO_COMPARE_FREE_PRIMARY 0x01
27
+static const char *colo_mode[] = {
86
+#define COLO_COMPARE_FREE_SECONDARY 0x02
28
+ [PRIMARY_IN] = "primary",
87
+
29
+ [SECONDARY_IN] = "secondary",
88
/* TODO: Should be configurable */
30
+};
89
#define REGULAR_PACKET_CHECK_MS 3000
31
90
32
static int compare_chr_send(CompareState *s,
91
@@ -XXX,XX +XXX,XX @@ static gint seq_sorter(Packet *a, Packet *b, gpointer data)
33
uint8_t *buf,
92
return ntohl(atcp->th_seq) - ntohl(btcp->th_seq);
34
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode, Connection **con)
93
}
35
ConnectionKey key;
94
36
Packet *pkt = NULL;
95
+static void fill_pkt_tcp_info(void *data, uint32_t *max_ack)
37
Connection *conn;
96
+{
38
+ int ret;
97
+ Packet *pkt = data;
39
98
+ struct tcphdr *tcphd;
40
if (mode == PRIMARY_IN) {
99
+
41
pkt = packet_new(s->pri_rs.buf,
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,
125
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode, Connection **con)
42
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode, Connection **con)
126
}
43
}
127
44
128
if (mode == PRIMARY_IN) {
45
if (mode == PRIMARY_IN) {
129
- if (!colo_insert_packet(&conn->primary_list, pkt)) {
46
- if (!colo_insert_packet(&conn->primary_list, pkt, &conn->pack)) {
130
+ if (!colo_insert_packet(&conn->primary_list, pkt, &conn->pack)) {
47
- error_report("colo compare primary queue size too big,"
131
error_report("colo compare primary queue size too big,"
48
- "drop packet");
132
"drop packet");
49
- }
133
}
50
+ ret = colo_insert_packet(&conn->primary_list, pkt, &conn->pack);
134
} else {
51
} else {
135
- if (!colo_insert_packet(&conn->secondary_list, pkt)) {
52
- if (!colo_insert_packet(&conn->secondary_list, pkt, &conn->sack)) {
136
+ if (!colo_insert_packet(&conn->secondary_list, pkt, &conn->sack)) {
53
- error_report("colo compare secondary queue size too big,"
137
error_report("colo compare secondary queue size too big,"
54
- "drop packet");
138
"drop packet");
55
- }
139
}
56
+ ret = colo_insert_packet(&conn->secondary_list, pkt, &conn->sack);
140
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode, Connection **con)
57
}
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
+
58
+
149
+static void colo_release_primary_pkt(CompareState *s, Packet *pkt)
59
+ if (!ret) {
150
+{
60
+ trace_colo_compare_drop_packet(colo_mode[mode],
151
+ int ret;
61
+ "queue size too big, drop packet");
152
+ ret = compare_chr_send(s,
62
+ packet_destroy(pkt, NULL);
153
+ pkt->data,
63
+ pkt = NULL;
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
+ }
64
+ }
202
+
65
+
203
+ /* one part of secondary packet payload still need to be compared */
66
*con = conn;
204
+ if (!after(ppkt->seq_end, spkt->seq_end)) {
67
205
+ if (colo_compare_packet_payload(ppkt, spkt,
68
return 0;
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;
272
}
273
+ ppkt = g_queue_pop_head(&conn->primary_list);
274
+sec:
275
+ if (g_queue_is_empty(&conn->secondary_list)) {
276
+ g_queue_push_head(&conn->primary_list, ppkt);
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
69
diff --git a/net/trace-events b/net/trace-events
575
index XXXXXXX..XXXXXXX 100644
70
index XXXXXXX..XXXXXXX 100644
576
--- a/net/trace-events
71
--- a/net/trace-events
577
+++ b/net/trace-events
72
+++ b/net/trace-events
578
@@ -XXX,XX +XXX,XX @@ colo_compare_icmp_miscompare(const char *sta, int size) ": %s = %d"
73
@@ -XXX,XX +XXX,XX @@ colo_proxy_main(const char *chr) ": %s"
74
75
# colo-compare.c
76
colo_compare_main(const char *chr) ": %s"
77
+colo_compare_drop_packet(const char *queue, const char *chr) ": %s: %s"
78
colo_compare_udp_miscompare(const char *sta, int size) ": %s = %d"
79
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"
80
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) ""
587
--
81
--
588
2.7.4
82
2.5.0
589
83
590
84
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
gently asked by his automatic reply :)
3
libFuzzer found using 'qemu-system-i386 -M q35':
4
4
5
qemu: hardware error: e1000e: PSRCTL.BSIZE0 cannot be zero
6
CPU #0:
7
EAX=00000000 EBX=00000000 ECX=00000000 EDX=00000663
8
ESI=00000000 EDI=00000000 EBP=00000000 ESP=00000000
9
EIP=0000fff0 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
10
ES =0000 00000000 0000ffff 00009300
11
CS =f000 ffff0000 0000ffff 00009b00
12
SS =0000 00000000 0000ffff 00009300
13
DS =0000 00000000 0000ffff 00009300
14
FS =0000 00000000 0000ffff 00009300
15
GS =0000 00000000 0000ffff 00009300
16
LDT=0000 00000000 0000ffff 00008200
17
TR =0000 00000000 0000ffff 00008b00
18
GDT= 00000000 0000ffff
19
IDT= 00000000 0000ffff
20
CR0=60000010 CR2=00000000 CR3=00000000 CR4=00000000
21
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
22
DR6=ffff0ff0 DR7=00000400
23
EFER=0000000000000000
24
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
25
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
26
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
27
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
28
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
29
XMM00=00000000000000000000000000000000 XMM01=00000000000000000000000000000000
30
XMM02=00000000000000000000000000000000 XMM03=00000000000000000000000000000000
31
XMM04=00000000000000000000000000000000 XMM05=00000000000000000000000000000000
32
XMM06=00000000000000000000000000000000 XMM07=00000000000000000000000000000000
33
==1988== ERROR: libFuzzer: deadly signal
34
#6 0x7fae4d3ea894 in __GI_abort (/lib64/libc.so.6+0x22894)
35
#7 0x563f4cc59a1d in hw_error (qemu-fuzz-i386+0xe8ca1d)
36
#8 0x563f4d7c93f2 in e1000e_set_psrctl (qemu-fuzz-i386+0x19fc3f2)
37
#9 0x563f4d7b798f in e1000e_core_write (qemu-fuzz-i386+0x19ea98f)
38
#10 0x563f4d7afc46 in e1000e_mmio_write (qemu-fuzz-i386+0x19e2c46)
39
#11 0x563f4cc9a0a7 in memory_region_write_accessor (qemu-fuzz-i386+0xecd0a7)
40
#12 0x563f4cc99c13 in access_with_adjusted_size (qemu-fuzz-i386+0xeccc13)
41
#13 0x563f4cc987b4 in memory_region_dispatch_write (qemu-fuzz-i386+0xecb7b4)
42
43
It simply sent the following 2 I/O command to the e1000e
44
PCI BAR #2 I/O region:
45
46
writew 0x0100 0x0c00 # RCTL = E1000_RCTL_DTYP_MASK
47
writeb 0x2170 0x00 # PSRCTL = 0
48
49
2813 static void
50
2814 e1000e_set_psrctl(E1000ECore *core, int index, uint32_t val)
51
2815 {
52
2816 if (core->mac[RCTL] & E1000_RCTL_DTYP_MASK) {
53
2817
54
2818 if ((val & E1000_PSRCTL_BSIZE0_MASK) == 0) {
55
2819 hw_error("e1000e: PSRCTL.BSIZE0 cannot be zero");
56
2820 }
57
58
Instead of calling hw_error() which abort the process (it is
59
meant for CPU fatal error condition, not for device logging),
60
log the invalid request with qemu_log_mask(LOG_GUEST_ERROR)
61
and return, ignoring the request.
62
63
Cc: qemu-stable@nongnu.org
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
64
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
65
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
---
66
---
8
MAINTAINERS | 8 ++++----
67
hw/net/e1000e_core.c | 10 +++++++---
9
1 file changed, 4 insertions(+), 4 deletions(-)
68
1 file changed, 7 insertions(+), 3 deletions(-)
10
69
11
diff --git a/MAINTAINERS b/MAINTAINERS
70
diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
12
index XXXXXXX..XXXXXXX 100644
71
index XXXXXXX..XXXXXXX 100644
13
--- a/MAINTAINERS
72
--- a/hw/net/e1000e_core.c
14
+++ b/MAINTAINERS
73
+++ b/hw/net/e1000e_core.c
15
@@ -XXX,XX +XXX,XX @@ F: hw/scsi/mfi.h
74
@@ -XXX,XX +XXX,XX @@
16
F: tests/megasas-test.c
75
*/
17
76
18
Network packet abstractions
77
#include "qemu/osdep.h"
19
-M: Dmitry Fleytman <dmitry@daynix.com>
78
+#include "qemu/log.h"
20
+M: Dmitry Fleytman <dmitry.fleytman@gmail.com>
79
#include "net/net.h"
21
S: Maintained
80
#include "net/tap.h"
22
F: include/net/eth.h
81
-#include "hw/hw.h"
23
F: net/eth.c
82
#include "hw/pci/msi.h"
24
@@ -XXX,XX +XXX,XX @@ F: hw/net/net_rx_pkt*
83
#include "hw/pci/msix.h"
25
F: hw/net/net_tx_pkt*
84
#include "sysemu/runstate.h"
26
85
@@ -XXX,XX +XXX,XX @@ e1000e_set_psrctl(E1000ECore *core, int index, uint32_t val)
27
Vmware
86
if (core->mac[RCTL] & E1000_RCTL_DTYP_MASK) {
28
-M: Dmitry Fleytman <dmitry@daynix.com>
87
29
+M: Dmitry Fleytman <dmitry.fleytman@gmail.com>
88
if ((val & E1000_PSRCTL_BSIZE0_MASK) == 0) {
30
S: Maintained
89
- hw_error("e1000e: PSRCTL.BSIZE0 cannot be zero");
31
F: hw/net/vmxnet*
90
+ qemu_log_mask(LOG_GUEST_ERROR,
32
F: hw/scsi/vmw_pvscsi*
91
+ "e1000e: PSRCTL.BSIZE0 cannot be zero");
33
@@ -XXX,XX +XXX,XX @@ F: hw/mem/nvdimm.c
92
+ return;
34
F: include/hw/mem/nvdimm.h
93
}
35
94
36
e1000x
95
if ((val & E1000_PSRCTL_BSIZE1_MASK) == 0) {
37
-M: Dmitry Fleytman <dmitry@daynix.com>
96
- hw_error("e1000e: PSRCTL.BSIZE1 cannot be zero");
38
+M: Dmitry Fleytman <dmitry.fleytman@gmail.com>
97
+ qemu_log_mask(LOG_GUEST_ERROR,
39
S: Maintained
98
+ "e1000e: PSRCTL.BSIZE1 cannot be zero");
40
F: hw/net/e1000x*
99
+ return;
41
100
}
42
e1000e
101
}
43
-M: Dmitry Fleytman <dmitry@daynix.com>
44
+M: Dmitry Fleytman <dmitry.fleytman@gmail.com>
45
S: Maintained
46
F: hw/net/e1000e*
47
102
48
--
103
--
49
2.7.4
104
2.5.0
50
105
51
106
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
QEMU can emulate hubs to connect NICs and netdevs. This is currently
3
It's been deprecated since QEMU v3.1, so it's time to finally
4
primarily used for the mis-named 'vlan' feature of the networking
4
remove it. The "id" parameter can simply be used instead.
5
subsystem. Now the 'vlan' feature has been marked as deprecated, since
6
its name is rather confusing and the users often rather mis-configure
7
their network when trying to use it. But while the 'vlan' parameter
8
should be removed at one point in time, the basic idea of emulating
9
a hub in QEMU is still good: It's useful for bundling up the output of
10
multiple NICs into one single l2tp netdev for example.
11
5
12
Now to be able to use the hubport feature without 'vlan's, there is one
6
Reviewed-by: Eric Blake <eblake@redhat.com>
13
missing piece: The possibility to connect a hubport to a netdev, too.
14
This patch adds this possibility by introducing a new "netdev=..."
15
parameter to the hubports.
16
17
To bundle up the output of multiple NICs into one socket netdev, you can
18
now run QEMU with these parameters for example:
19
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>
38
Signed-off-by: Thomas Huth <thuth@redhat.com>
7
Signed-off-by: Thomas Huth <thuth@redhat.com>
39
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
40
---
9
---
41
net/hub.c | 27 +++++++++++++++++++++------
10
docs/system/deprecated.rst | 15 +++++++++------
42
net/hub.h | 3 ++-
11
net/net.c | 10 +---------
43
net/net.c | 2 +-
12
qapi/net.json | 3 ---
44
qapi/net.json | 4 +++-
13
3 files changed, 10 insertions(+), 18 deletions(-)
45
qemu-options.hx | 8 +++++---
46
5 files changed, 32 insertions(+), 12 deletions(-)
47
14
48
diff --git a/net/hub.c b/net/hub.c
15
diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst
49
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
50
--- a/net/hub.c
17
--- a/docs/system/deprecated.rst
51
+++ b/net/hub.c
18
+++ b/docs/system/deprecated.rst
52
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ The 'file' driver for drives is no longer appropriate for character or host
53
*/
20
devices and will only accept regular files (S_IFREG). The correct driver
54
21
for these file types is 'host_cdrom' or 'host_device' as appropriate.
55
#include "qemu/osdep.h"
22
56
+#include "qapi/error.h"
23
-``-net ...,name=``\ *name* (since 3.1)
57
#include "monitor/monitor.h"
24
-''''''''''''''''''''''''''''''''''''''
58
#include "net/net.h"
25
-
59
#include "clients.h"
26
-The ``name`` parameter of the ``-net`` option is a synonym
60
@@ -XXX,XX +XXX,XX @@ static NetClientInfo net_hub_port_info = {
27
-for the ``id`` parameter, which should now be used instead.
61
.cleanup = net_hub_port_cleanup,
28
-
62
};
29
``-smp`` (invalid topologies) (since 3.1)
63
30
'''''''''''''''''''''''''''''''''''''''''
64
-static NetHubPort *net_hub_port_new(NetHub *hub, const char *name)
31
65
+static NetHubPort *net_hub_port_new(NetHub *hub, const char *name,
32
@@ -XXX,XX +XXX,XX @@ What follows is a record of recently removed, formerly deprecated
66
+ NetClientState *hubpeer)
33
features that serves as a record for users who have encountered
67
{
34
trouble after a recent upgrade.
68
NetClientState *nc;
35
69
NetHubPort *port;
36
+System emulator command line arguments
70
@@ -XXX,XX +XXX,XX @@ static NetHubPort *net_hub_port_new(NetHub *hub, const char *name)
37
+--------------------------------------
71
name = default_name;
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;
102
}
103
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)
115
{
116
const NetdevHubPortOptions *hubport;
117
+ NetClientState *hubpeer = NULL;
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
+
38
+
132
+ net_hub_add_port(hubport->hubid, name, hubpeer);
39
+``-net ...,name=``\ *name* (removed in 5.1)
40
+'''''''''''''''''''''''''''''''''''''''''''
133
+
41
+
134
return 0;
42
+The ``name`` parameter of the ``-net`` option was a synonym
135
}
43
+for the ``id`` parameter, which should now be used instead.
136
44
+
137
diff --git a/net/hub.h b/net/hub.h
45
QEMU Machine Protocol (QMP) commands
138
index XXXXXXX..XXXXXXX 100644
46
------------------------------------
139
--- a/net/hub.h
47
140
+++ b/net/hub.h
141
@@ -XXX,XX +XXX,XX @@
142
143
#include "qemu-common.h"
144
145
-NetClientState *net_hub_add_port(int hub_id, const char *name);
146
+NetClientState *net_hub_add_port(int hub_id, const char *name,
147
+ NetClientState *hubpeer);
148
NetClientState *net_hub_find_client_by_name(int hub_id, const char *name);
149
void net_hub_info(Monitor *mon);
150
void net_hub_check_clients(void);
151
diff --git a/net/net.c b/net/net.c
48
diff --git a/net/net.c b/net/net.c
152
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
153
--- a/net/net.c
50
--- a/net/net.c
154
+++ b/net/net.c
51
+++ b/net/net.c
155
@@ -XXX,XX +XXX,XX @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp)
52
@@ -XXX,XX +XXX,XX @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp)
156
/* Do not add to a vlan if it's a nic with a netdev= parameter. */
53
{
157
if (netdev->type != NET_CLIENT_DRIVER_NIC ||
54
Netdev legacy = {0};
158
!opts->u.nic.has_netdev) {
55
const Netdev *netdev;
159
- peer = net_hub_add_port(net->has_vlan ? net->vlan : 0, NULL);
56
- const char *name;
160
+ peer = net_hub_add_port(net->has_vlan ? net->vlan : 0, NULL, NULL);
57
NetClientState *peer = NULL;
58
59
if (is_netdev) {
60
netdev = object;
61
- name = netdev->id;
62
63
if (netdev->type == NET_CLIENT_DRIVER_NIC ||
64
!net_client_init_fun[netdev->type]) {
65
@@ -XXX,XX +XXX,XX @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp)
66
const NetLegacyOptions *opts = net->opts;
67
legacy.id = net->id;
68
netdev = &legacy;
69
- /* missing optional values have been initialized to "all bits zero" */
70
- name = net->has_id ? net->id : net->name;
71
-
72
- if (net->has_name) {
73
- warn_report("The 'name' parameter is deprecated, use 'id' instead");
74
- }
75
76
/* Map the old options to the new flat type */
77
switch (opts->type) {
78
@@ -XXX,XX +XXX,XX @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp)
161
}
79
}
162
80
}
163
if (net->has_vlan && !vlan_warned) {
81
82
- if (net_client_init_fun[netdev->type](netdev, name, peer, errp) < 0) {
83
+ if (net_client_init_fun[netdev->type](netdev, netdev->id, peer, errp) < 0) {
84
/* FIXME drop when all init functions store an Error */
85
if (errp && !*errp) {
86
error_setg(errp, QERR_DEVICE_INIT_FAILED,
164
diff --git a/qapi/net.json b/qapi/net.json
87
diff --git a/qapi/net.json b/qapi/net.json
165
index XXXXXXX..XXXXXXX 100644
88
index XXXXXXX..XXXXXXX 100644
166
--- a/qapi/net.json
89
--- a/qapi/net.json
167
+++ b/qapi/net.json
90
+++ b/qapi/net.json
168
@@ -XXX,XX +XXX,XX @@
91
@@ -XXX,XX +XXX,XX @@
169
# Connect two or more net clients through a software hub.
170
#
92
#
171
# @hubid: hub identifier number
93
# @id: identifier for monitor commands
172
+# @netdev: used to connect hub to a netdev instead of a device (since 2.12)
94
#
95
-# @name: identifier for monitor commands, ignored if @id is present
96
-#
97
# @opts: device type specific properties (legacy)
173
#
98
#
174
# Since: 1.2
99
# Since: 1.2
100
@@ -XXX,XX +XXX,XX @@
101
{ 'struct': 'NetLegacy',
102
'data': {
103
'*id': 'str',
104
- '*name': 'str',
105
'opts': 'NetLegacyOptions' } }
106
175
##
107
##
176
{ 'struct': 'NetdevHubPortOptions',
177
'data': {
178
- 'hubid': 'int32' } }
179
+ 'hubid': 'int32',
180
+ '*netdev': 'str' } }
181
182
##
183
# @NetdevNetmapOptions:
184
diff --git a/qemu-options.hx b/qemu-options.hx
185
index XXXXXXX..XXXXXXX 100644
186
--- a/qemu-options.hx
187
+++ b/qemu-options.hx
188
@@ -XXX,XX +XXX,XX @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
189
#endif
190
"-netdev vhost-user,id=str,chardev=dev[,vhostforce=on|off]\n"
191
" configure a vhost-user network, backed by a chardev 'dev'\n"
192
- "-netdev hubport,id=str,hubid=n\n"
193
+ "-netdev hubport,id=str,hubid=n[,netdev=nd]\n"
194
" configure a hub port on QEMU VLAN 'n'\n", QEMU_ARCH_ALL)
195
DEF("net", HAS_ARG, QEMU_OPTION_net,
196
"-net nic[,vlan=n][,netdev=nd][,macaddr=mac][,model=type][,name=str][,addr=str][,vectors=v]\n"
197
@@ -XXX,XX +XXX,XX @@ vde_switch -F -sock /tmp/myswitch
198
qemu-system-i386 linux.img -net nic -net vde,sock=/tmp/myswitch
199
@end example
200
201
-@item -netdev hubport,id=@var{id},hubid=@var{hubid}
202
+@item -netdev hubport,id=@var{id},hubid=@var{hubid}[,netdev=@var{nd}]
203
204
Create a hub port on QEMU "vlan" @var{hubid}.
205
206
The hubport netdev lets you connect a NIC to a QEMU "vlan" instead of a single
207
netdev. @code{-net} and @code{-device} with parameter @option{vlan} create the
208
-required hub automatically.
209
+required hub automatically. Alternatively, you can also connect the hubport
210
+to another netdev with ID @var{nd} by using the @option{netdev=@var{nd}}
211
+option.
212
213
@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off][,queues=n]
214
215
--
108
--
216
2.7.4
109
2.5.0
217
110
218
111
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
The vlan concept is marked as deprecated, so we should not use
3
Now that the "name" parameter is gone, there is hardly any difference
4
this for examples in the documentation anymore.
4
between NetLegacy and Netdev anymore, so we can drop NetLegacy and always
5
use Netdev to simplify the code quite a bit.
6
7
The only two differences that were really left between Netdev and NetLegacy:
8
9
1) NetLegacy does not allow a "hubport" type. We can continue to block
10
this with a simple check in net_client_init1() for this type.
11
12
2) The "id" parameter was optional in NetLegacy (and an internal id
13
was chosen via assign_name() during initialization), but it is mandatory
14
for Netdev. To avoid that the visitor code bails out here, we have to
15
add an internal id to the QemuOpts already earlier now.
5
16
6
Signed-off-by: Thomas Huth <thuth@redhat.com>
17
Signed-off-by: Thomas Huth <thuth@redhat.com>
18
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
19
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
20
---
9
qemu-options.hx | 4 ++--
21
net/net.c | 77 ++++++++++-------------------------------------------------
10
1 file changed, 2 insertions(+), 2 deletions(-)
22
qapi/net.json | 46 -----------------------------------
11
23
2 files changed, 13 insertions(+), 110 deletions(-)
12
diff --git a/qemu-options.hx b/qemu-options.hx
24
25
diff --git a/net/net.c b/net/net.c
13
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
14
--- a/qemu-options.hx
27
--- a/net/net.c
15
+++ b/qemu-options.hx
28
+++ b/net/net.c
16
@@ -XXX,XX +XXX,XX @@ qemu-system-i386 linux.img -net nic -net tap
29
@@ -XXX,XX +XXX,XX @@ static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])(
17
#launch a QEMU instance with two NICs, each one connected
30
};
18
#to a TAP device
31
19
qemu-system-i386 linux.img \
32
20
- -net nic,vlan=0 -net tap,vlan=0,ifname=tap0 \
33
-static int net_client_init1(const void *object, bool is_netdev, Error **errp)
21
- -net nic,vlan=1 -net tap,vlan=1,ifname=tap1
34
+static int net_client_init1(const Netdev *netdev, bool is_netdev, Error **errp)
22
+ -netdev tap,id=nd0,ifname=tap0 -device e1000,netdev=nd0 \
35
{
23
+ -netdev tap,id=nd1,ifname=tap1 -device rtl8139,netdev=nd1
36
- Netdev legacy = {0};
24
@end example
37
- const Netdev *netdev;
25
38
NetClientState *peer = NULL;
26
@example
39
40
if (is_netdev) {
41
- netdev = object;
42
-
43
if (netdev->type == NET_CLIENT_DRIVER_NIC ||
44
!net_client_init_fun[netdev->type]) {
45
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type",
46
@@ -XXX,XX +XXX,XX @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp)
47
return -1;
48
}
49
} else {
50
- const NetLegacy *net = object;
51
- const NetLegacyOptions *opts = net->opts;
52
- legacy.id = net->id;
53
- netdev = &legacy;
54
-
55
- /* Map the old options to the new flat type */
56
- switch (opts->type) {
57
- case NET_LEGACY_OPTIONS_TYPE_NONE:
58
+ if (netdev->type == NET_CLIENT_DRIVER_NONE) {
59
return 0; /* nothing to do */
60
- case NET_LEGACY_OPTIONS_TYPE_NIC:
61
- legacy.type = NET_CLIENT_DRIVER_NIC;
62
- legacy.u.nic = opts->u.nic;
63
- break;
64
- case NET_LEGACY_OPTIONS_TYPE_USER:
65
- legacy.type = NET_CLIENT_DRIVER_USER;
66
- legacy.u.user = opts->u.user;
67
- break;
68
- case NET_LEGACY_OPTIONS_TYPE_TAP:
69
- legacy.type = NET_CLIENT_DRIVER_TAP;
70
- legacy.u.tap = opts->u.tap;
71
- break;
72
- case NET_LEGACY_OPTIONS_TYPE_L2TPV3:
73
- legacy.type = NET_CLIENT_DRIVER_L2TPV3;
74
- legacy.u.l2tpv3 = opts->u.l2tpv3;
75
- break;
76
- case NET_LEGACY_OPTIONS_TYPE_SOCKET:
77
- legacy.type = NET_CLIENT_DRIVER_SOCKET;
78
- legacy.u.socket = opts->u.socket;
79
- break;
80
- case NET_LEGACY_OPTIONS_TYPE_VDE:
81
- legacy.type = NET_CLIENT_DRIVER_VDE;
82
- legacy.u.vde = opts->u.vde;
83
- break;
84
- case NET_LEGACY_OPTIONS_TYPE_BRIDGE:
85
- legacy.type = NET_CLIENT_DRIVER_BRIDGE;
86
- legacy.u.bridge = opts->u.bridge;
87
- break;
88
- case NET_LEGACY_OPTIONS_TYPE_NETMAP:
89
- legacy.type = NET_CLIENT_DRIVER_NETMAP;
90
- legacy.u.netmap = opts->u.netmap;
91
- break;
92
- case NET_LEGACY_OPTIONS_TYPE_VHOST_USER:
93
- legacy.type = NET_CLIENT_DRIVER_VHOST_USER;
94
- legacy.u.vhost_user = opts->u.vhost_user;
95
- break;
96
- default:
97
- abort();
98
}
99
-
100
- if (!net_client_init_fun[netdev->type]) {
101
+ if (netdev->type == NET_CLIENT_DRIVER_HUBPORT ||
102
+ !net_client_init_fun[netdev->type]) {
103
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type",
104
"a net backend type (maybe it is not compiled "
105
"into this binary)");
106
@@ -XXX,XX +XXX,XX @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp)
107
108
/* Do not add to a hub if it's a nic with a netdev= parameter. */
109
if (netdev->type != NET_CLIENT_DRIVER_NIC ||
110
- !opts->u.nic.has_netdev) {
111
+ !netdev->u.nic.has_netdev) {
112
peer = net_hub_add_port(0, NULL, NULL);
113
}
114
}
115
@@ -XXX,XX +XXX,XX @@ static void show_netdevs(void)
116
static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp)
117
{
118
gchar **substrings = NULL;
119
- void *object = NULL;
120
+ Netdev *object = NULL;
121
Error *err = NULL;
122
int ret = -1;
123
Visitor *v = opts_visitor_new(opts);
124
@@ -XXX,XX +XXX,XX @@ static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp)
125
}
126
}
127
128
- if (is_netdev) {
129
- visit_type_Netdev(v, NULL, (Netdev **)&object, &err);
130
- } else {
131
- visit_type_NetLegacy(v, NULL, (NetLegacy **)&object, &err);
132
+ /* Create an ID for -net if the user did not specify one */
133
+ if (!is_netdev && !qemu_opts_id(opts)) {
134
+ static int idx;
135
+ qemu_opts_set_id(opts, g_strdup_printf("__org.qemu.net%i", idx++));
136
}
137
138
+ visit_type_Netdev(v, NULL, &object, &err);
139
+
140
if (!err) {
141
ret = net_client_init1(object, is_netdev, &err);
142
}
143
144
- if (is_netdev) {
145
- qapi_free_Netdev(object);
146
- } else {
147
- qapi_free_NetLegacy(object);
148
- }
149
+ qapi_free_Netdev(object);
150
151
out:
152
error_propagate(errp, err);
153
diff --git a/qapi/net.json b/qapi/net.json
154
index XXXXXXX..XXXXXXX 100644
155
--- a/qapi/net.json
156
+++ b/qapi/net.json
157
@@ -XXX,XX +XXX,XX @@
158
'vhost-user': 'NetdevVhostUserOptions' } }
159
160
##
161
-# @NetLegacy:
162
-#
163
-# Captures the configuration of a network device; legacy.
164
-#
165
-# @id: identifier for monitor commands
166
-#
167
-# @opts: device type specific properties (legacy)
168
-#
169
-# Since: 1.2
170
-##
171
-{ 'struct': 'NetLegacy',
172
- 'data': {
173
- '*id': 'str',
174
- 'opts': 'NetLegacyOptions' } }
175
-
176
-##
177
-# @NetLegacyOptionsType:
178
-#
179
-# Since: 1.2
180
-##
181
-{ 'enum': 'NetLegacyOptionsType',
182
- 'data': ['none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde',
183
- 'bridge', 'netmap', 'vhost-user'] }
184
-
185
-##
186
-# @NetLegacyOptions:
187
-#
188
-# Like Netdev, but for use only by the legacy command line options
189
-#
190
-# Since: 1.2
191
-##
192
-{ 'union': 'NetLegacyOptions',
193
- 'base': { 'type': 'NetLegacyOptionsType' },
194
- 'discriminator': 'type',
195
- 'data': {
196
- 'nic': 'NetLegacyNicOptions',
197
- 'user': 'NetdevUserOptions',
198
- 'tap': 'NetdevTapOptions',
199
- 'l2tpv3': 'NetdevL2TPv3Options',
200
- 'socket': 'NetdevSocketOptions',
201
- 'vde': 'NetdevVdeOptions',
202
- 'bridge': 'NetdevBridgeOptions',
203
- 'netmap': 'NetdevNetmapOptions',
204
- 'vhost-user': 'NetdevVhostUserOptions' } }
205
-
206
-##
207
# @NetFilterDirection:
208
#
209
# Indicates whether a netfilter is attached to a netdev's transmit queue or
27
--
210
--
28
2.7.4
211
2.5.0
29
212
30
213
diff view generated by jsdifflib