1
The following changes since commit 7d3660e79830a069f1848bb4fa1cdf8f666424fb:
1
The following changes since commit 23895cbd82be95428e90168b12e925d0d3ca2f06:
2
2
3
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging (2020-06-12 23:06:22 +0100)
3
Merge remote-tracking branch 'remotes/awilliam/tags/vfio-update-20201123.0' into staging (2020-11-23 18:51:13 +0000)
4
4
5
are available in the git repository at:
5
are available in the git repository at:
6
6
7
https://github.com/jasowang/qemu.git tags/net-pull-request
7
https://github.com/jasowang/qemu.git tags/net-pull-request
8
8
9
for you to fetch changes up to 955aab203f932b8a7c23ff9c58ba036997cb3ed8:
9
for you to fetch changes up to 9925990d01a92564af55f6f69d0f5f59b47609b1:
10
10
11
net: Drop the NetLegacy structure, always use Netdev instead (2020-06-16 14:40:40 +0800)
11
net: Use correct default-path macro for downscript (2020-11-24 10:40:17 +0800)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
14
15
----------------------------------------------------------------
15
----------------------------------------------------------------
16
Derek Su (1):
16
Keqian Zhu (1):
17
colo-compare: Fix memory leak in packet_enqueue()
17
net: Use correct default-path macro for downscript
18
18
19
Helge Deller (1):
19
Paolo Bonzini (1):
20
Fix tulip breakage
20
net: do not exit on "netdev_add help" monitor command
21
21
22
Jason Wang (1):
22
Prasad J Pandit (1):
23
net: use peer when purging queue in qemu_flush_or_purge_queue_packets()
23
hw/net/e1000e: advance desc_offset in case of null descriptor
24
24
25
Lukas Straub (6):
25
Yuri Benditovich (1):
26
net/colo-compare.c: Create event_bh with the right AioContext
26
net: purge queued rx packets on queue deletion
27
chardev/char.c: Use qemu_co_sleep_ns if in coroutine
28
net/colo-compare.c: Fix deadlock in compare_chr_send
29
net/colo-compare.c: Only hexdump packets if tracing is enabled
30
net/colo-compare.c: Check that colo-compare is active
31
net/colo-compare.c: Correct ordering in complete and finalize
32
27
33
Philippe Mathieu-Daudé (3):
28
yuanjungong (1):
34
hw/net/tulip: Fix 'Descriptor Error' definition
29
tap: fix a memory leak
35
hw/net/tulip: Log descriptor overflows
36
hw/net/e1000e: Do not abort() on invalid PSRCTL register value
37
30
38
Sai Pavan Boddu (11):
31
hw/net/e1000e_core.c | 8 +++---
39
net: cadence_gem: Fix debug statements
32
include/net/net.h | 1 +
40
net: cadence_gem: Fix the queue address update during wrap around
33
monitor/hmp-cmds.c | 6 ++++
41
net: cadence_gem: Fix irq update w.r.t queue
34
net/net.c | 80 +++++++++++++++++++++++++++-------------------------
42
net: cadence_gem: Define access permission for interrupt registers
35
net/tap.c | 5 +++-
43
net: cadence_gem: Set ISR according to queue in use
36
5 files changed, 57 insertions(+), 43 deletions(-)
44
net: cadence_gem: Move tx/rx packet buffert to CadenceGEMState
45
net: cadence_gem: Fix up code style
46
net: cadence_gem: Add support for jumbo frames
47
net: cadnece_gem: Update irq_read_clear field of designcfg_debug1 reg
48
net: cadence_gem: Update the reset value for interrupt mask register
49
net: cadence_gem: TX_LAST bit should be set by guest
50
51
Thomas Huth (2):
52
net: Drop the legacy "name" parameter from the -net option
53
net: Drop the NetLegacy structure, always use Netdev instead
54
55
Tong Ho (1):
56
net: cadence_gem: Fix RX address filtering
57
58
Yuri Benditovich (7):
59
virtio-net: implement RSS configuration command
60
virtio-net: implement RX RSS processing
61
tap: allow extended virtio header with hash info
62
virtio-net: reference implementation of hash report
63
vmstate.h: provide VMSTATE_VARRAY_UINT16_ALLOC macro
64
virtio-net: add migration support for RSS and hash report
65
virtio-net: align RSC fields with updated virtio-net header
66
67
chardev/char.c | 7 +-
68
docs/system/deprecated.rst | 15 +-
69
hw/net/cadence_gem.c | 458 +++++++++++++++++++++++------------------
70
hw/net/e1000e_core.c | 10 +-
71
hw/net/trace-events | 3 +
72
hw/net/tulip.c | 12 +-
73
hw/net/tulip.h | 2 +-
74
hw/net/virtio-net.c | 387 ++++++++++++++++++++++++++++++----
75
include/hw/net/cadence_gem.h | 6 +
76
include/hw/virtio/virtio-net.h | 16 ++
77
include/migration/vmstate.h | 10 +
78
net/colo-compare.c | 277 ++++++++++++++++++-------
79
net/colo.c | 7 +
80
net/colo.h | 1 +
81
net/net.c | 89 ++------
82
net/tap.c | 3 +-
83
net/trace-events | 1 +
84
qapi/net.json | 49 -----
85
18 files changed, 904 insertions(+), 449 deletions(-)
86
37
87
38
88
diff view generated by jsdifflib
Deleted patch
1
From: Yuri Benditovich <yuri.benditovich@daynix.com>
2
1
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
Deleted patch
1
From: Yuri Benditovich <yuri.benditovich@daynix.com>
2
1
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/virtio-net.c | 88 +++++++++++++++++++++++++++++++++++++++++-
11
include/hw/virtio/virtio-net.h | 1 +
12
2 files changed, 87 insertions(+), 2 deletions(-)
13
14
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/net/virtio-net.c
17
+++ b/hw/net/virtio-net.c
18
@@ -XXX,XX +XXX,XX @@
19
#include "trace.h"
20
#include "monitor/qdev.h"
21
#include "hw/pci/pci.h"
22
+#include "net_rx_pkt.h"
23
24
#define VIRTIO_NET_VM_VERSION 11
25
26
@@ -XXX,XX +XXX,XX @@ static int receive_filter(VirtIONet *n, const uint8_t *buf, int size)
27
return 0;
28
}
29
30
+static uint8_t virtio_net_get_hash_type(bool isip4,
31
+ bool isip6,
32
+ bool isudp,
33
+ bool istcp,
34
+ uint32_t types)
35
+{
36
+ if (isip4) {
37
+ if (istcp && (types & VIRTIO_NET_RSS_HASH_TYPE_TCPv4)) {
38
+ return NetPktRssIpV4Tcp;
39
+ }
40
+ if (isudp && (types & VIRTIO_NET_RSS_HASH_TYPE_UDPv4)) {
41
+ return NetPktRssIpV4Udp;
42
+ }
43
+ if (types & VIRTIO_NET_RSS_HASH_TYPE_IPv4) {
44
+ return NetPktRssIpV4;
45
+ }
46
+ } else if (isip6) {
47
+ uint32_t mask = VIRTIO_NET_RSS_HASH_TYPE_TCP_EX |
48
+ VIRTIO_NET_RSS_HASH_TYPE_TCPv6;
49
+
50
+ if (istcp && (types & mask)) {
51
+ return (types & VIRTIO_NET_RSS_HASH_TYPE_TCP_EX) ?
52
+ NetPktRssIpV6TcpEx : NetPktRssIpV6Tcp;
53
+ }
54
+ mask = VIRTIO_NET_RSS_HASH_TYPE_UDP_EX | VIRTIO_NET_RSS_HASH_TYPE_UDPv6;
55
+ if (isudp && (types & mask)) {
56
+ return (types & VIRTIO_NET_RSS_HASH_TYPE_UDP_EX) ?
57
+ NetPktRssIpV6UdpEx : NetPktRssIpV6Udp;
58
+ }
59
+ mask = VIRTIO_NET_RSS_HASH_TYPE_IP_EX | VIRTIO_NET_RSS_HASH_TYPE_IPv6;
60
+ if (types & mask) {
61
+ return (types & VIRTIO_NET_RSS_HASH_TYPE_IP_EX) ?
62
+ NetPktRssIpV6Ex : NetPktRssIpV6;
63
+ }
64
+ }
65
+ return 0xff;
66
+}
67
+
68
+static int virtio_net_process_rss(NetClientState *nc, const uint8_t *buf,
69
+ size_t size)
70
+{
71
+ VirtIONet *n = qemu_get_nic_opaque(nc);
72
+ unsigned int index = nc->queue_index, new_index;
73
+ struct NetRxPkt *pkt = n->rx_pkt;
74
+ uint8_t net_hash_type;
75
+ uint32_t hash;
76
+ bool isip4, isip6, isudp, istcp;
77
+
78
+ net_rx_pkt_set_protocols(pkt, buf + n->host_hdr_len,
79
+ size - n->host_hdr_len);
80
+ net_rx_pkt_get_protocols(pkt, &isip4, &isip6, &isudp, &istcp);
81
+ if (isip4 && (net_rx_pkt_get_ip4_info(pkt)->fragment)) {
82
+ istcp = isudp = false;
83
+ }
84
+ if (isip6 && (net_rx_pkt_get_ip6_info(pkt)->fragment)) {
85
+ istcp = isudp = false;
86
+ }
87
+ net_hash_type = virtio_net_get_hash_type(isip4, isip6, isudp, istcp,
88
+ n->rss_data.hash_types);
89
+ if (net_hash_type > NetPktRssIpV6UdpEx) {
90
+ return n->rss_data.default_queue;
91
+ }
92
+
93
+ hash = net_rx_pkt_calc_rss_hash(pkt, net_hash_type, n->rss_data.key);
94
+ new_index = hash & (n->rss_data.indirections_len - 1);
95
+ new_index = n->rss_data.indirections_table[new_index];
96
+ if (index == new_index) {
97
+ return -1;
98
+ }
99
+ return new_index;
100
+}
101
+
102
static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
103
- size_t size)
104
+ size_t size, bool no_rss)
105
{
106
VirtIONet *n = qemu_get_nic_opaque(nc);
107
VirtIONetQueue *q = virtio_net_get_subqueue(nc);
108
@@ -XXX,XX +XXX,XX @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
109
return -1;
110
}
111
112
+ if (!no_rss && n->rss_data.enabled) {
113
+ int index = virtio_net_process_rss(nc, buf, size);
114
+ if (index >= 0) {
115
+ NetClientState *nc2 = qemu_get_subqueue(n->nic, index);
116
+ return virtio_net_receive_rcu(nc2, buf, size, true);
117
+ }
118
+ }
119
+
120
/* hdr_len refers to the header we supply to the guest */
121
if (!virtio_net_has_buffers(q, size + n->guest_hdr_len - n->host_hdr_len)) {
122
return 0;
123
@@ -XXX,XX +XXX,XX @@ static ssize_t virtio_net_do_receive(NetClientState *nc, const uint8_t *buf,
124
{
125
RCU_READ_LOCK_GUARD();
126
127
- return virtio_net_receive_rcu(nc, buf, size);
128
+ return virtio_net_receive_rcu(nc, buf, size, false);
129
}
130
131
static void virtio_net_rsc_extract_unit4(VirtioNetRscChain *chain,
132
@@ -XXX,XX +XXX,XX @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
133
134
QTAILQ_INIT(&n->rsc_chains);
135
n->qdev = dev;
136
+
137
+ net_rx_pkt_init(&n->rx_pkt, false);
138
}
139
140
static void virtio_net_device_unrealize(DeviceState *dev)
141
@@ -XXX,XX +XXX,XX @@ static void virtio_net_device_unrealize(DeviceState *dev)
142
qemu_del_nic(n->nic);
143
virtio_net_rsc_cleanup(n);
144
g_free(n->rss_data.indirections_table);
145
+ net_rx_pkt_uninit(n->rx_pkt);
146
virtio_cleanup(vdev);
147
}
148
149
diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
150
index XXXXXXX..XXXXXXX 100644
151
--- a/include/hw/virtio/virtio-net.h
152
+++ b/include/hw/virtio/virtio-net.h
153
@@ -XXX,XX +XXX,XX @@ struct VirtIONet {
154
DeviceListener primary_listener;
155
Notifier migration_state;
156
VirtioNetRssData rss_data;
157
+ struct NetRxPkt *rx_pkt;
158
};
159
160
void virtio_net_set_netclient_name(VirtIONet *n, const char *name,
161
--
162
2.5.0
163
164
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Prasad J Pandit <pjp@fedoraproject.org>
2
2
3
libFuzzer found using 'qemu-system-i386 -M q35':
3
While receiving packets via e1000e_write_packet_to_guest() routine,
4
'desc_offset' is advanced only when RX descriptor is processed. And
5
RX descriptor is not processed if it has NULL buffer address.
6
This may lead to an infinite loop condition. Increament 'desc_offset'
7
to process next descriptor in the ring to avoid infinite loop.
4
8
5
qemu: hardware error: e1000e: PSRCTL.BSIZE0 cannot be zero
9
Reported-by: Cheol-woo Myung <330cjfdn@gmail.com>
6
CPU #0:
10
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
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
64
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
65
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
66
---
12
---
67
hw/net/e1000e_core.c | 10 +++++++---
13
hw/net/e1000e_core.c | 8 ++++----
68
1 file changed, 7 insertions(+), 3 deletions(-)
14
1 file changed, 4 insertions(+), 4 deletions(-)
69
15
70
diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
16
diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
71
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
72
--- a/hw/net/e1000e_core.c
18
--- a/hw/net/e1000e_core.c
73
+++ b/hw/net/e1000e_core.c
19
+++ b/hw/net/e1000e_core.c
74
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ e1000e_write_packet_to_guest(E1000ECore *core, struct NetRxPkt *pkt,
75
*/
21
(const char *) &fcs_pad, e1000x_fcs_len(core->mac));
76
22
}
77
#include "qemu/osdep.h"
23
}
78
+#include "qemu/log.h"
24
- desc_offset += desc_size;
79
#include "net/net.h"
25
- if (desc_offset >= total_size) {
80
#include "net/tap.h"
26
- is_last = true;
81
-#include "hw/hw.h"
27
- }
82
#include "hw/pci/msi.h"
28
} else { /* as per intel docs; skip descriptors with null buf addr */
83
#include "hw/pci/msix.h"
29
trace_e1000e_rx_null_descriptor();
84
#include "sysemu/runstate.h"
85
@@ -XXX,XX +XXX,XX @@ e1000e_set_psrctl(E1000ECore *core, int index, uint32_t val)
86
if (core->mac[RCTL] & E1000_RCTL_DTYP_MASK) {
87
88
if ((val & E1000_PSRCTL_BSIZE0_MASK) == 0) {
89
- hw_error("e1000e: PSRCTL.BSIZE0 cannot be zero");
90
+ qemu_log_mask(LOG_GUEST_ERROR,
91
+ "e1000e: PSRCTL.BSIZE0 cannot be zero");
92
+ return;
93
}
30
}
94
31
+ desc_offset += desc_size;
95
if ((val & E1000_PSRCTL_BSIZE1_MASK) == 0) {
32
+ if (desc_offset >= total_size) {
96
- hw_error("e1000e: PSRCTL.BSIZE1 cannot be zero");
33
+ is_last = true;
97
+ qemu_log_mask(LOG_GUEST_ERROR,
34
+ }
98
+ "e1000e: PSRCTL.BSIZE1 cannot be zero");
35
99
+ return;
36
e1000e_write_rx_descr(core, desc, is_last ? core->rx_pkt : NULL,
100
}
37
rss_info, do_ps ? ps_hdr_len : 0, &bastate.written);
101
}
102
103
--
38
--
104
2.5.0
39
2.7.4
105
40
106
41
diff view generated by jsdifflib
1
From: Lukas Straub <lukasstraub2@web.de>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
The chr_out chardev is connected to a filter-redirector
3
"netdev_add help" is causing QEMU to exit because the code that
4
running in the main loop. qemu_chr_fe_write_all might block
4
invokes show_netdevs is shared between CLI and HMP processing.
5
here in compare_chr_send if the (socket-)buffer is full.
5
Move the check to the callers so that exit(0) remains only
6
If another filter-redirector in the main loop want's to
6
in the CLI flow.
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
7
11
Fix this by converting compare_chr_send to a coroutine and
8
"netdev_add help" is not fixed by this patch; that is left for
12
putting the packets in a send queue.
9
later work.
13
10
14
Signed-off-by: Lukas Straub <lukasstraub2@web.de>
11
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
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>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
19
---
13
---
20
net/colo-compare.c | 193 ++++++++++++++++++++++++++++++++++++++++-------------
14
include/net/net.h | 1 +
21
net/colo.c | 7 ++
15
monitor/hmp-cmds.c | 6 +++++
22
net/colo.h | 1 +
16
net/net.c | 68 +++++++++++++++++++++++++++---------------------------
23
3 files changed, 156 insertions(+), 45 deletions(-)
17
3 files changed, 41 insertions(+), 34 deletions(-)
24
18
25
diff --git a/net/colo-compare.c b/net/colo-compare.c
19
diff --git a/include/net/net.h b/include/net/net.h
26
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
27
--- a/net/colo-compare.c
21
--- a/include/net/net.h
28
+++ b/net/colo-compare.c
22
+++ b/include/net/net.h
23
@@ -XXX,XX +XXX,XX @@ extern const char *host_net_devices[];
24
25
/* from net.c */
26
int net_client_parse(QemuOptsList *opts_list, const char *str);
27
+void show_netdevs(void);
28
int net_init_clients(Error **errp);
29
void net_check_clients(void);
30
void net_cleanup(void);
31
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/monitor/hmp-cmds.c
34
+++ b/monitor/hmp-cmds.c
29
@@ -XXX,XX +XXX,XX @@
35
@@ -XXX,XX +XXX,XX @@
30
#include "migration/migration.h"
36
#include "qemu/option.h"
31
#include "util.h"
37
#include "qemu/timer.h"
32
38
#include "qemu/sockets.h"
33
+#include "block/aio-wait.h"
39
+#include "qemu/help_option.h"
34
+#include "qemu/coroutine.h"
40
#include "monitor/monitor-internal.h"
35
+
41
#include "qapi/error.h"
36
#define TYPE_COLO_COMPARE "colo-compare"
42
#include "qapi/clone-visitor.h"
37
#define COLO_COMPARE(obj) \
43
@@ -XXX,XX +XXX,XX @@ void hmp_netdev_add(Monitor *mon, const QDict *qdict)
38
OBJECT_CHECK(CompareState, (obj), TYPE_COLO_COMPARE)
44
{
39
@@ -XXX,XX +XXX,XX @@ static int event_unhandled_count;
45
Error *err = NULL;
40
* |packet | |packet + |packet | |packet +
46
QemuOpts *opts;
41
* +--------+ +--------+ +--------+ +--------+
47
+ const char *type = qdict_get_try_str(qdict, "type");
42
*/
48
43
+
49
+ if (type && is_help_option(type)) {
44
+typedef struct SendCo {
50
+ show_netdevs();
45
+ Coroutine *co;
51
+ return;
46
+ struct CompareState *s;
52
+ }
47
+ CharBackend *chr;
53
opts = qemu_opts_from_qdict(qemu_find_opts("netdev"), qdict, &err);
48
+ GQueue send_list;
54
if (err) {
49
+ bool notify_remote_frame;
55
goto out;
50
+ bool done;
56
diff --git a/net/net.c b/net/net.c
51
+ int ret;
57
index XXXXXXX..XXXXXXX 100644
52
+} SendCo;
58
--- a/net/net.c
53
+
59
+++ b/net/net.c
54
+typedef struct SendEntry {
60
@@ -XXX,XX +XXX,XX @@
55
+ uint32_t size;
61
#include "qemu/config-file.h"
56
+ uint32_t vnet_hdr_len;
62
#include "qemu/ctype.h"
57
+ uint8_t *buf;
63
#include "qemu/iov.h"
58
+} SendEntry;
64
+#include "qemu/qemu-print.h"
59
+
65
#include "qemu/main-loop.h"
60
typedef struct CompareState {
66
#include "qemu/option.h"
61
Object parent;
67
#include "qapi/error.h"
62
68
@@ -XXX,XX +XXX,XX @@ static int net_client_init1(const Netdev *netdev, bool is_netdev, Error **errp)
63
@@ -XXX,XX +XXX,XX @@ typedef struct CompareState {
69
return 0;
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
}
70
}
109
71
110
/*
72
-static void show_netdevs(void)
111
@@ -XXX,XX +XXX,XX @@ static void colo_compare_connection(void *opaque, void *user_data)
73
+void show_netdevs(void)
74
{
75
int idx;
76
const char *available_netdevs[] = {
77
@@ -XXX,XX +XXX,XX @@ static void show_netdevs(void)
78
#endif
79
};
80
81
- printf("Available netdev backend types:\n");
82
+ qemu_printf("Available netdev backend types:\n");
83
for (idx = 0; idx < ARRAY_SIZE(available_netdevs); idx++) {
84
- puts(available_netdevs[idx]);
85
+ qemu_printf("%s\n", available_netdevs[idx]);
112
}
86
}
113
}
87
}
114
88
115
-static int compare_chr_send(CompareState *s,
89
@@ -XXX,XX +XXX,XX @@ static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp)
116
- const uint8_t *buf,
90
int ret = -1;
117
- uint32_t size,
91
Visitor *v = opts_visitor_new(opts);
118
- uint32_t vnet_hdr_len,
92
119
- bool notify_remote_frame)
93
- const char *type = qemu_opt_get(opts, "type");
120
+static void coroutine_fn _compare_chr_send(void *opaque)
94
-
121
{
95
- if (is_netdev && type && is_help_option(type)) {
122
+ SendCo *sendco = opaque;
96
- show_netdevs();
123
+ CompareState *s = sendco->s;
97
- exit(0);
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 {
98
- } else {
139
- ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len));
99
- /* Parse convenience option format ip6-net=fec0::0[/64] */
140
- }
100
- const char *ip6_net = qemu_opt_get(opts, "ipv6-net");
141
+ ret = qemu_chr_fe_write_all(sendco->chr, (uint8_t *)&len, sizeof(len));
101
+ /* Parse convenience option format ip6-net=fec0::0[/64] */
142
102
+ const char *ip6_net = qemu_opt_get(opts, "ipv6-net");
143
- if (ret != sizeof(len)) {
103
144
- goto err;
104
- if (ip6_net) {
145
- }
105
- char *prefix_addr;
146
+ if (ret != sizeof(len)) {
106
- unsigned long prefix_len = 64; /* Default 64bit prefix length. */
147
+ g_free(entry->buf);
107
+ if (ip6_net) {
148
+ g_slice_free(SendEntry, entry);
108
+ char *prefix_addr;
149
+ goto err;
109
+ unsigned long prefix_len = 64; /* Default 64bit prefix length. */
110
111
- substrings = g_strsplit(ip6_net, "/", 2);
112
- if (!substrings || !substrings[0]) {
113
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "ipv6-net",
114
- "a valid IPv6 prefix");
115
- goto out;
116
- }
117
+ substrings = g_strsplit(ip6_net, "/", 2);
118
+ if (!substrings || !substrings[0]) {
119
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "ipv6-net",
120
+ "a valid IPv6 prefix");
121
+ goto out;
150
+ }
122
+ }
151
123
152
- if (s->vnet_hdr) {
124
- prefix_addr = substrings[0];
153
- /*
125
+ prefix_addr = substrings[0];
154
- * We send vnet header len make other module(like filter-redirector)
126
155
- * know how to parse net packet correctly.
127
- /* Handle user-specified prefix length. */
156
- */
128
- if (substrings[1] &&
157
- len = htonl(vnet_hdr_len);
129
- qemu_strtoul(substrings[1], NULL, 10, &prefix_len))
158
+ if (!sendco->notify_remote_frame && s->vnet_hdr) {
130
- {
159
+ /*
131
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
160
+ * We send vnet header len make other module(like filter-redirector)
132
- "ipv6-prefixlen", "a number");
161
+ * know how to parse net packet correctly.
133
- goto out;
162
+ */
134
- }
163
+ len = htonl(entry->vnet_hdr_len);
135
-
164
136
- qemu_opt_set(opts, "ipv6-prefix", prefix_addr, &error_abort);
165
- if (!notify_remote_frame) {
137
- qemu_opt_set_number(opts, "ipv6-prefixlen", prefix_len,
166
- ret = qemu_chr_fe_write_all(&s->chr_out,
138
- &error_abort);
167
+ ret = qemu_chr_fe_write_all(sendco->chr,
139
- qemu_opt_unset(opts, "ipv6-net");
168
(uint8_t *)&len,
140
+ /* Handle user-specified prefix length. */
169
sizeof(len));
141
+ if (substrings[1] &&
170
+
142
+ qemu_strtoul(substrings[1], NULL, 10, &prefix_len))
171
+ if (ret != sizeof(len)) {
143
+ {
172
+ g_free(entry->buf);
144
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
173
+ g_slice_free(SendEntry, entry);
145
+ "ipv6-prefixlen", "a number");
174
+ goto err;
146
+ goto out;
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
}
147
}
188
+
148
+
189
+ g_free(entry->buf);
149
+ qemu_opt_set(opts, "ipv6-prefix", prefix_addr, &error_abort);
190
+ g_slice_free(SendEntry, entry);
150
+ qemu_opt_set_number(opts, "ipv6-prefixlen", prefix_len,
151
+ &error_abort);
152
+ qemu_opt_unset(opts, "ipv6-net");
191
}
153
}
192
154
193
+ sendco->ret = 0;
155
/* Create an ID for -net if the user did not specify one */
194
+ goto out;
156
@@ -XXX,XX +XXX,XX @@ static int net_init_client(void *dummy, QemuOpts *opts, Error **errp)
157
158
static int net_init_netdev(void *dummy, QemuOpts *opts, Error **errp)
159
{
160
+ const char *type = qemu_opt_get(opts, "type");
195
+
161
+
196
+err:
162
+ if (type && is_help_option(type)) {
197
+ while (!g_queue_is_empty(&sendco->send_list)) {
163
+ show_netdevs();
198
+ SendEntry *entry = g_queue_pop_tail(&sendco->send_list);
164
+ exit(0);
199
+ g_free(entry->buf);
200
+ g_slice_free(SendEntry, entry);
201
+ }
165
+ }
202
+ sendco->ret = ret < 0 ? ret : -EIO;
166
return net_client_init(opts, true, errp);
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
}
167
}
262
168
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
--
169
--
368
2.5.0
170
2.7.4
369
171
370
172
diff view generated by jsdifflib
1
From: Yuri Benditovich <yuri.benditovich@daynix.com>
1
From: Yuri Benditovich <yuri.benditovich@daynix.com>
2
2
3
Save and restore RSS/hash report configuration.
3
https://bugzilla.redhat.com/show_bug.cgi?id=1829272
4
When deleting queue pair, purge pending RX packets if any.
5
Example of problematic flow:
6
1. Bring up q35 VM with tap (vhost off) and virtio-net or e1000e
7
2. Run ping flood to the VM NIC ( 1 ms interval)
8
3. Hot unplug the NIC device (device_del)
9
During unplug process one or more packets come, the NIC
10
can't receive, tap disables read_poll
11
4. Hot plug the device (device_add) with the same netdev
12
The tap stays with read_poll disabled and does not receive
13
any packets anymore (tap_send never triggered)
4
14
5
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
15
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
16
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
---
17
---
8
hw/net/virtio-net.c | 37 +++++++++++++++++++++++++++++++++++++
18
net/net.c | 12 ++++++++----
9
1 file changed, 37 insertions(+)
19
1 file changed, 8 insertions(+), 4 deletions(-)
10
20
11
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
21
diff --git a/net/net.c b/net/net.c
12
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/net/virtio-net.c
23
--- a/net/net.c
14
+++ b/hw/net/virtio-net.c
24
+++ b/net/net.c
15
@@ -XXX,XX +XXX,XX @@ static int virtio_net_post_load_device(void *opaque, int version_id)
25
@@ -XXX,XX +XXX,XX @@ void qemu_del_nic(NICState *nic)
26
27
qemu_macaddr_set_free(&nic->conf->macaddr);
28
29
- /* If this is a peer NIC and peer has already been deleted, free it now. */
30
- if (nic->peer_deleted) {
31
- for (i = 0; i < queues; i++) {
32
- qemu_free_net_client(qemu_get_subqueue(nic, i)->peer);
33
+ for (i = 0; i < queues; i++) {
34
+ NetClientState *nc = qemu_get_subqueue(nic, i);
35
+ /* If this is a peer NIC and peer has already been deleted, free it now. */
36
+ if (nic->peer_deleted) {
37
+ qemu_free_net_client(nc->peer);
38
+ } else if (nc->peer) {
39
+ /* if there are RX packets pending, complete them */
40
+ qemu_purge_queued_packets(nc->peer);
16
}
41
}
17
}
42
}
18
43
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
--
44
--
74
2.5.0
45
2.7.4
75
46
76
47
diff view generated by jsdifflib
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
1
From: yuanjungong <ruc_gongyuanjun@163.com>
2
2
3
Enabling debug breaks the build, Fix them and make debug statements
3
Close fd before returning.
4
always compilable. Fix few statements to use sized integer casting.
5
4
6
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
5
Buglink: https://bugs.launchpad.net/qemu/+bug/1904486
7
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
6
7
Signed-off-by: yuanjungong <ruc_gongyuanjun@163.com>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
10
---
10
hw/net/cadence_gem.c | 27 +++++++++++++--------------
11
net/tap.c | 2 ++
11
1 file changed, 13 insertions(+), 14 deletions(-)
12
1 file changed, 2 insertions(+)
12
13
13
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
14
diff --git a/net/tap.c b/net/tap.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/net/cadence_gem.c
16
--- a/net/tap.c
16
+++ b/hw/net/cadence_gem.c
17
+++ b/net/tap.c
17
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ int net_init_tap(const Netdev *netdev, const char *name,
18
#include "sysemu/dma.h"
19
if (ret < 0) {
19
#include "net/checksum.h"
20
error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d",
20
21
name, fd);
21
-#ifdef CADENCE_GEM_ERR_DEBUG
22
+ close(fd);
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;
23
return -1;
50
}
24
}
51
25
52
- DB_PRINT("copy %u bytes to 0x%" PRIx64 "\n",
26
@@ -XXX,XX +XXX,XX @@ int net_init_tap(const Netdev *netdev, const char *name,
53
- MIN(bytes_to_copy, rxbufsize),
27
vhostfdname, vnet_hdr, fd, &err);
54
- rx_desc_get_buffer(s, s->rx_desc[q]));
28
if (err) {
55
+ DB_PRINT("copy %" PRIu32 " bytes to 0x%" PRIx64 "\n",
29
error_propagate(errp, err);
56
+ MIN(bytes_to_copy, rxbufsize),
30
+ close(fd);
57
+ rx_desc_get_buffer(s, s->rx_desc[q]));
31
return -1;
58
32
}
59
/* Copy packet data to emulated DMA buffer */
33
} else if (tap->has_fds) {
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
--
34
--
73
2.5.0
35
2.7.4
74
36
75
37
diff view generated by jsdifflib
1
From: Yuri Benditovich <yuri.benditovich@daynix.com>
1
From: Keqian Zhu <zhukeqian1@huawei.com>
2
2
3
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
3
Fixes: 63c4db4c2e6d (net: relocate paths to helpers and scripts)
4
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
4
Signed-off-by: Jason Wang <jasowang@redhat.com>
5
Signed-off-by: Jason Wang <jasowang@redhat.com>
5
---
6
---
6
net/tap.c | 3 ++-
7
net/tap.c | 3 ++-
7
1 file changed, 2 insertions(+), 1 deletion(-)
8
1 file changed, 2 insertions(+), 1 deletion(-)
8
9
9
diff --git a/net/tap.c b/net/tap.c
10
diff --git a/net/tap.c b/net/tap.c
10
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
11
--- a/net/tap.c
12
--- a/net/tap.c
12
+++ b/net/tap.c
13
+++ b/net/tap.c
13
@@ -XXX,XX +XXX,XX @@ static void tap_set_vnet_hdr_len(NetClientState *nc, int len)
14
@@ -XXX,XX +XXX,XX @@ free_fail:
14
15
script = default_script = get_relocated_path(DEFAULT_NETWORK_SCRIPT);
15
assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
16
}
16
assert(len == sizeof(struct virtio_net_hdr_mrg_rxbuf) ||
17
if (!downscript) {
17
- len == sizeof(struct virtio_net_hdr));
18
- downscript = default_downscript = get_relocated_path(DEFAULT_NETWORK_SCRIPT);
18
+ len == sizeof(struct virtio_net_hdr) ||
19
+ downscript = default_downscript =
19
+ len == sizeof(struct virtio_net_hdr_v1_hash));
20
+ get_relocated_path(DEFAULT_NETWORK_DOWN_SCRIPT);
20
21
}
21
tap_fd_set_vnet_hdr_len(s->fd, len);
22
22
s->host_vnet_hdr_len = len;
23
if (tap->has_ifname) {
23
--
24
--
24
2.5.0
25
2.7.4
25
26
26
27
diff view generated by jsdifflib
Deleted patch
1
From: Yuri Benditovich <yuri.benditovich@daynix.com>
2
1
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
Deleted patch
1
From: Yuri Benditovich <yuri.benditovich@daynix.com>
2
1
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
Deleted patch
1
From: Yuri Benditovich <yuri.benditovich@daynix.com>
2
1
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
Deleted patch
1
From: Helge Deller <deller@gmx.de>
2
1
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
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
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
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
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
Deleted patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
2
1
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
Deleted patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
2
1
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
Deleted patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
2
1
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
Deleted patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
2
1
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
Deleted patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
2
1
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
Deleted patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
2
1
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
Deleted patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
2
1
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
Deleted patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
2
1
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
Deleted patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
2
1
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
Deleted patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
2
1
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
Deleted patch
1
From: Tong Ho <tong.ho@xilinx.com>
2
1
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
Deleted 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:
5
1
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
Deleted patch
1
From: Lukas Straub <lukasstraub2@web.de>
2
1
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
Deleted patch
1
From: Lukas Straub <lukasstraub2@web.de>
2
1
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
Deleted patch
1
From: Lukas Straub <lukasstraub2@web.de>
2
1
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
Deleted patch
1
From: Lukas Straub <lukasstraub2@web.de>
2
1
3
If the colo-compare object is removed before failover and a
4
checkpoint happens, qemu crashes because it tries to lock
5
the destroyed event_mtx in colo_notify_compares_event.
6
7
Fix this by checking if everything is initialized by
8
introducing a new variable colo_compare_active which
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.
13
14
With this it also is again possible to use colo without
15
colo-compare (periodic mode) and to use multiple colo-compare
16
for multiple network interfaces.
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>
22
Signed-off-by: Jason Wang <jasowang@redhat.com>
23
---
24
net/colo-compare.c | 35 +++++++++++++++++++++++++++++------
25
1 file changed, 29 insertions(+), 6 deletions(-)
26
27
diff --git a/net/colo-compare.c b/net/colo-compare.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/net/colo-compare.c
30
+++ b/net/colo-compare.c
31
@@ -XXX,XX +XXX,XX @@ static NotifierList colo_compare_notifiers =
32
#define REGULAR_PACKET_CHECK_MS 3000
33
#define DEFAULT_TIME_OUT_MS 3000
34
35
+static QemuMutex colo_compare_mutex;
36
+static bool colo_compare_active;
37
static QemuMutex event_mtx;
38
static QemuCond event_complete_cond;
39
static int event_unhandled_count;
40
@@ -XXX,XX +XXX,XX @@ static void check_old_packet_regular(void *opaque)
41
void colo_notify_compares_event(void *opaque, int event, Error **errp)
42
{
43
CompareState *s;
44
+ qemu_mutex_lock(&colo_compare_mutex);
45
+
46
+ if (!colo_compare_active) {
47
+ qemu_mutex_unlock(&colo_compare_mutex);
48
+ return;
49
+ }
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)
54
}
55
56
qemu_mutex_unlock(&event_mtx);
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);
82
-
83
s->connection_track_table = g_hash_table_new_full(connection_key_hash,
84
connection_key_equal,
85
g_free,
86
@@ -XXX,XX +XXX,XX @@ static void colo_compare_finalize(Object *obj)
87
88
qemu_bh_delete(s->event_bh);
89
90
+ qemu_mutex_lock(&colo_compare_mutex);
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);
117
}
118
119
+static void __attribute__((__constructor__)) colo_compare_init_globals(void)
120
+{
121
+ colo_compare_active = false;
122
+ qemu_mutex_init(&colo_compare_mutex);
123
+}
124
+
125
static const TypeInfo colo_compare_info = {
126
.name = TYPE_COLO_COMPARE,
127
.parent = TYPE_OBJECT,
128
--
129
2.5.0
130
131
diff view generated by jsdifflib
Deleted patch
1
From: Lukas Straub <lukasstraub2@web.de>
2
1
3
In colo_compare_complete, insert CompareState into net_compares
4
only after everything has been initialized.
5
In colo_compare_finalize, remove CompareState from net_compares
6
before anything is deinitialized.
7
8
Signed-off-by: Lukas Straub <lukasstraub2@web.de>
9
Reviewed-by: Zhang Chen <chen.zhang@intel.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 | 45 +++++++++++++++++++++++----------------------
14
1 file changed, 23 insertions(+), 22 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 @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
21
s->vnet_hdr);
22
}
23
24
- qemu_mutex_lock(&colo_compare_mutex);
25
- if (!colo_compare_active) {
26
- qemu_mutex_init(&event_mtx);
27
- qemu_cond_init(&event_complete_cond);
28
- colo_compare_active = true;
29
- }
30
- QTAILQ_INSERT_TAIL(&net_compares, s, next);
31
- qemu_mutex_unlock(&colo_compare_mutex);
32
-
33
s->out_sendco.s = s;
34
s->out_sendco.chr = &s->chr_out;
35
s->out_sendco.notify_remote_frame = false;
36
@@ -XXX,XX +XXX,XX @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
37
connection_destroy);
38
39
colo_compare_iothread(s);
40
+
41
+ qemu_mutex_lock(&colo_compare_mutex);
42
+ if (!colo_compare_active) {
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;
51
}
52
53
@@ -XXX,XX +XXX,XX @@ static void colo_compare_finalize(Object *obj)
54
CompareState *s = COLO_COMPARE(obj);
55
CompareState *tmp = NULL;
56
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
- }
63
-
64
- if (s->iothread) {
65
- colo_compare_timer_del(s);
66
- }
67
-
68
- qemu_bh_delete(s->event_bh);
69
-
70
qemu_mutex_lock(&colo_compare_mutex);
71
QTAILQ_FOREACH(tmp, &net_compares, next) {
72
if (tmp == s) {
73
@@ -XXX,XX +XXX,XX @@ static void colo_compare_finalize(Object *obj)
74
}
75
qemu_mutex_unlock(&colo_compare_mutex);
76
77
+ qemu_chr_fe_deinit(&s->chr_pri_in, false);
78
+ qemu_chr_fe_deinit(&s->chr_sec_in, false);
79
+ qemu_chr_fe_deinit(&s->chr_out, false);
80
+ if (s->notify_dev) {
81
+ qemu_chr_fe_deinit(&s->chr_notify_dev, false);
82
+ }
83
+
84
+ if (s->iothread) {
85
+ colo_compare_timer_del(s);
86
+ }
87
+
88
+ qemu_bh_delete(s->event_bh);
89
+
90
AioContext *ctx = iothread_get_aio_context(s->iothread);
91
aio_context_acquire(ctx);
92
AIO_WAIT_WHILE(ctx, !s->out_sendco.done);
93
--
94
2.5.0
95
96
diff view generated by jsdifflib
Deleted patch
1
From: Derek Su <dereksu@qnap.com>
2
1
3
The patch is to fix the "pkt" memory leak in packet_enqueue().
4
The allocated "pkt" needs to be freed if the colo compare
5
primary or secondary queue is too big.
6
7
Replace the error_report of full queue with a trace event.
8
9
Signed-off-by: Derek Su <dereksu@qnap.com>
10
Reviewed-by: Zhang Chen <chen.zhang@intel.com>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
13
Signed-off-by: Jason Wang <jasowang@redhat.com>
14
---
15
net/colo-compare.c | 23 +++++++++++++++--------
16
net/trace-events | 1 +
17
2 files changed, 16 insertions(+), 8 deletions(-)
18
19
diff --git a/net/colo-compare.c b/net/colo-compare.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/net/colo-compare.c
22
+++ b/net/colo-compare.c
23
@@ -XXX,XX +XXX,XX @@ enum {
24
SECONDARY_IN,
25
};
26
27
+static const char *colo_mode[] = {
28
+ [PRIMARY_IN] = "primary",
29
+ [SECONDARY_IN] = "secondary",
30
+};
31
32
static int compare_chr_send(CompareState *s,
33
uint8_t *buf,
34
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode, Connection **con)
35
ConnectionKey key;
36
Packet *pkt = NULL;
37
Connection *conn;
38
+ int ret;
39
40
if (mode == PRIMARY_IN) {
41
pkt = packet_new(s->pri_rs.buf,
42
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode, Connection **con)
43
}
44
45
if (mode == PRIMARY_IN) {
46
- if (!colo_insert_packet(&conn->primary_list, pkt, &conn->pack)) {
47
- error_report("colo compare primary queue size too big,"
48
- "drop packet");
49
- }
50
+ ret = colo_insert_packet(&conn->primary_list, pkt, &conn->pack);
51
} else {
52
- if (!colo_insert_packet(&conn->secondary_list, pkt, &conn->sack)) {
53
- error_report("colo compare secondary queue size too big,"
54
- "drop packet");
55
- }
56
+ ret = colo_insert_packet(&conn->secondary_list, pkt, &conn->sack);
57
}
58
+
59
+ if (!ret) {
60
+ trace_colo_compare_drop_packet(colo_mode[mode],
61
+ "queue size too big, drop packet");
62
+ packet_destroy(pkt, NULL);
63
+ pkt = NULL;
64
+ }
65
+
66
*con = conn;
67
68
return 0;
69
diff --git a/net/trace-events b/net/trace-events
70
index XXXXXXX..XXXXXXX 100644
71
--- a/net/trace-events
72
+++ b/net/trace-events
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"
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"
81
--
82
2.5.0
83
84
diff view generated by jsdifflib
Deleted patch
1
From: Thomas Huth <thuth@redhat.com>
2
1
3
It's been deprecated since QEMU v3.1, so it's time to finally
4
remove it. The "id" parameter can simply be used instead.
5
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Signed-off-by: Thomas Huth <thuth@redhat.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
10
docs/system/deprecated.rst | 15 +++++++++------
11
net/net.c | 10 +---------
12
qapi/net.json | 3 ---
13
3 files changed, 10 insertions(+), 18 deletions(-)
14
15
diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst
16
index XXXXXXX..XXXXXXX 100644
17
--- a/docs/system/deprecated.rst
18
+++ b/docs/system/deprecated.rst
19
@@ -XXX,XX +XXX,XX @@ The 'file' driver for drives is no longer appropriate for character or host
20
devices and will only accept regular files (S_IFREG). The correct driver
21
for these file types is 'host_cdrom' or 'host_device' as appropriate.
22
23
-``-net ...,name=``\ *name* (since 3.1)
24
-''''''''''''''''''''''''''''''''''''''
25
-
26
-The ``name`` parameter of the ``-net`` option is a synonym
27
-for the ``id`` parameter, which should now be used instead.
28
-
29
``-smp`` (invalid topologies) (since 3.1)
30
'''''''''''''''''''''''''''''''''''''''''
31
32
@@ -XXX,XX +XXX,XX @@ What follows is a record of recently removed, formerly deprecated
33
features that serves as a record for users who have encountered
34
trouble after a recent upgrade.
35
36
+System emulator command line arguments
37
+--------------------------------------
38
+
39
+``-net ...,name=``\ *name* (removed in 5.1)
40
+'''''''''''''''''''''''''''''''''''''''''''
41
+
42
+The ``name`` parameter of the ``-net`` option was a synonym
43
+for the ``id`` parameter, which should now be used instead.
44
+
45
QEMU Machine Protocol (QMP) commands
46
------------------------------------
47
48
diff --git a/net/net.c b/net/net.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/net/net.c
51
+++ b/net/net.c
52
@@ -XXX,XX +XXX,XX @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp)
53
{
54
Netdev legacy = {0};
55
const Netdev *netdev;
56
- const char *name;
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)
79
}
80
}
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,
87
diff --git a/qapi/net.json b/qapi/net.json
88
index XXXXXXX..XXXXXXX 100644
89
--- a/qapi/net.json
90
+++ b/qapi/net.json
91
@@ -XXX,XX +XXX,XX @@
92
#
93
# @id: identifier for monitor commands
94
#
95
-# @name: identifier for monitor commands, ignored if @id is present
96
-#
97
# @opts: device type specific properties (legacy)
98
#
99
# Since: 1.2
100
@@ -XXX,XX +XXX,XX @@
101
{ 'struct': 'NetLegacy',
102
'data': {
103
'*id': 'str',
104
- '*name': 'str',
105
'opts': 'NetLegacyOptions' } }
106
107
##
108
--
109
2.5.0
110
111
diff view generated by jsdifflib
Deleted patch
1
From: Thomas Huth <thuth@redhat.com>
2
1
3
Now that the "name" parameter is gone, there is hardly any difference
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.
16
17
Signed-off-by: Thomas Huth <thuth@redhat.com>
18
Reviewed-by: Eric Blake <eblake@redhat.com>
19
Signed-off-by: Jason Wang <jasowang@redhat.com>
20
---
21
net/net.c | 77 ++++++++++-------------------------------------------------
22
qapi/net.json | 46 -----------------------------------
23
2 files changed, 13 insertions(+), 110 deletions(-)
24
25
diff --git a/net/net.c b/net/net.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/net/net.c
28
+++ b/net/net.c
29
@@ -XXX,XX +XXX,XX @@ static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])(
30
};
31
32
33
-static int net_client_init1(const void *object, bool is_netdev, Error **errp)
34
+static int net_client_init1(const Netdev *netdev, bool is_netdev, Error **errp)
35
{
36
- Netdev legacy = {0};
37
- const Netdev *netdev;
38
NetClientState *peer = NULL;
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
210
--
211
2.5.0
212
213
diff view generated by jsdifflib