1
The following changes since commit 6632f6ff96f0537fc34cdc00c760656fc62e23c5:
1
The following changes since commit 3f429a3400822141651486193d6af625eeab05a5:
2
2
3
Merge remote-tracking branch 'remotes/famz/tags/block-and-testing-pull-request' into staging (2017-07-17 11:46:36 +0100)
3
Merge remote-tracking branch 'remotes/kraxel/tags/microvm-20200617-pull-request' into staging (2020-06-18 11:23:15 +0100)
4
4
5
are available in the git repository at:
5
are available in the git repository at:
6
6
7
https://github.com/jasowang/qemu.git tags/net-pull-request
7
https://github.com/jasowang/qemu.git tags/net-pull-request
8
8
9
for you to fetch changes up to 189ae6bb5ce1f5a322f8691d00fe942ba43dd601:
9
for you to fetch changes up to 71830d8430e65dd20aec4765d87e60336148e1a6:
10
10
11
virtio-net: fix offload ctrl endian (2017-07-17 20:13:56 +0800)
11
net: Drop the NetLegacy structure, always use Netdev instead (2020-06-18 21:05:52 +0800)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
14
15
- fix virtio-net ctrl offload endian
15
Changes from V1:
16
- vnet header support for variou COLO netfilters and compare thread
16
- Fix build failure for virtio-net
17
17
18
----------------------------------------------------------------
18
----------------------------------------------------------------
19
Derek Su (1):
20
colo-compare: Fix memory leak in packet_enqueue()
21
22
Helge Deller (1):
23
Fix tulip breakage
24
19
Jason Wang (1):
25
Jason Wang (1):
20
virtio-net: fix offload ctrl endian
26
net: use peer when purging queue in qemu_flush_or_purge_queue_packets()
21
27
22
Michal Privoznik (1):
28
Lukas Straub (6):
23
virtion-net: Prefer is_power_of_2()
29
net/colo-compare.c: Create event_bh with the right AioContext
30
chardev/char.c: Use qemu_co_sleep_ns if in coroutine
31
net/colo-compare.c: Fix deadlock in compare_chr_send
32
net/colo-compare.c: Only hexdump packets if tracing is enabled
33
net/colo-compare.c: Check that colo-compare is active
34
net/colo-compare.c: Correct ordering in complete and finalize
24
35
25
Zhang Chen (12):
36
Philippe Mathieu-Daudé (3):
26
net: Add vnet_hdr_len arguments in NetClientState
37
hw/net/tulip: Fix 'Descriptor Error' definition
27
net/net.c: Add vnet_hdr support in SocketReadState
38
hw/net/tulip: Log descriptor overflows
28
net/filter-mirror.c: Introduce parameter for filter_send()
39
hw/net/e1000e: Do not abort() on invalid PSRCTL register value
29
net/filter-mirror.c: Make filter mirror support vnet support.
30
net/filter-mirror.c: Add new option to enable vnet support for filter-redirector
31
net/colo.c: Make vnet_hdr_len as packet property
32
net/colo-compare.c: Introduce parameter for compare_chr_send()
33
net/colo-compare.c: Make colo-compare support vnet_hdr_len
34
net/colo.c: Add vnet packet parse feature in colo-proxy
35
net/colo-compare.c: Add vnet packet's tcp/udp/icmp compare
36
net/filter-rewriter.c: Make filter-rewriter support vnet_hdr_len
37
docs/colo-proxy.txt: Update colo-proxy usage of net driver with vnet_header
38
40
39
docs/colo-proxy.txt | 26 ++++++++++++++++
41
Sai Pavan Boddu (11):
40
hw/net/virtio-net.c | 4 ++-
42
net: cadence_gem: Fix debug statements
41
include/net/net.h | 10 ++++--
43
net: cadence_gem: Fix the queue address update during wrap around
42
net/colo-compare.c | 84 ++++++++++++++++++++++++++++++++++++++++++---------
44
net: cadence_gem: Fix irq update w.r.t queue
43
net/colo.c | 9 +++---
45
net: cadence_gem: Define access permission for interrupt registers
44
net/colo.h | 4 ++-
46
net: cadence_gem: Set ISR according to queue in use
45
net/filter-mirror.c | 75 +++++++++++++++++++++++++++++++++++++++++----
47
net: cadence_gem: Move tx/rx packet buffert to CadenceGEMState
46
net/filter-rewriter.c | 37 ++++++++++++++++++++++-
48
net: cadence_gem: Fix up code style
47
net/net.c | 37 ++++++++++++++++++++---
49
net: cadence_gem: Add support for jumbo frames
48
net/socket.c | 8 ++---
50
net: cadnece_gem: Update irq_read_clear field of designcfg_debug1 reg
49
qemu-options.hx | 19 ++++++------
51
net: cadence_gem: Update the reset value for interrupt mask register
50
11 files changed, 265 insertions(+), 48 deletions(-)
52
net: cadence_gem: TX_LAST bit should be set by guest
53
54
Thomas Huth (2):
55
net: Drop the legacy "name" parameter from the -net option
56
net: Drop the NetLegacy structure, always use Netdev instead
57
58
Tong Ho (1):
59
net: cadence_gem: Fix RX address filtering
60
61
Yuri Benditovich (7):
62
virtio-net: implement RSS configuration command
63
virtio-net: implement RX RSS processing
64
tap: allow extended virtio header with hash info
65
virtio-net: reference implementation of hash report
66
vmstate.h: provide VMSTATE_VARRAY_UINT16_ALLOC macro
67
virtio-net: add migration support for RSS and hash report
68
virtio-net: align RSC fields with updated virtio-net header
69
70
chardev/char.c | 7 +-
71
docs/system/deprecated.rst | 15 +-
72
hw/net/Makefile.objs | 1 +
73
hw/net/cadence_gem.c | 458 +++++++++++++++++++++++------------------
74
hw/net/e1000e_core.c | 10 +-
75
hw/net/trace-events | 3 +
76
hw/net/tulip.c | 12 +-
77
hw/net/tulip.h | 2 +-
78
hw/net/virtio-net.c | 387 ++++++++++++++++++++++++++++++----
79
include/hw/net/cadence_gem.h | 6 +
80
include/hw/virtio/virtio-net.h | 16 ++
81
include/migration/vmstate.h | 10 +
82
net/colo-compare.c | 277 ++++++++++++++++++-------
83
net/colo.c | 7 +
84
net/colo.h | 1 +
85
net/net.c | 89 ++------
86
net/tap.c | 3 +-
87
net/trace-events | 1 +
88
qapi/net.json | 49 -----
89
19 files changed, 905 insertions(+), 449 deletions(-)
51
90
52
91
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Yuri Benditovich <yuri.benditovich@daynix.com>
2
2
3
We add the vnet_hdr_support option for filter-mirror, default is disabled.
3
Optionally report RSS feature.
4
If you use virtio-net-pci or other driver needs vnet_hdr, please enable it.
4
Handle RSS configuration command and keep RSS parameters
5
You can use it for example:
5
in virtio-net device context.
6
-object filter-mirror,id=m0,netdev=hn0,queue=tx,outdev=mirror0,vnet_hdr_support
6
7
7
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
8
If it has vnet_hdr_support flag, we will change the sending packet format from
9
struct {int size; const uint8_t buf[];} to {int size; int vnet_hdr_len; const uint8_t buf[];}.
10
make other module(like colo-compare) know how to parse net packet correctly.
11
12
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
13
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
14
---
9
---
15
net/filter-mirror.c | 42 +++++++++++++++++++++++++++++++++++++++++-
10
hw/net/trace-events | 3 +
16
qemu-options.hx | 5 ++---
11
hw/net/virtio-net.c | 167 ++++++++++++++++++++++++++++++++++++++---
17
2 files changed, 43 insertions(+), 4 deletions(-)
12
include/hw/virtio/virtio-net.h | 13 ++++
18
13
3 files changed, 174 insertions(+), 9 deletions(-)
19
diff --git a/net/filter-mirror.c b/net/filter-mirror.c
14
15
diff --git a/hw/net/trace-events b/hw/net/trace-events
20
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
21
--- a/net/filter-mirror.c
17
--- a/hw/net/trace-events
22
+++ b/net/filter-mirror.c
18
+++ b/hw/net/trace-events
23
@@ -XXX,XX +XXX,XX @@ typedef struct MirrorState {
19
@@ -XXX,XX +XXX,XX @@ virtio_net_announce_notify(void) ""
24
CharBackend chr_in;
20
virtio_net_announce_timer(int round) "%d"
25
CharBackend chr_out;
21
virtio_net_handle_announce(int round) "%d"
26
SocketReadState rs;
22
virtio_net_post_load_device(void)
27
+ bool vnet_hdr;
23
+virtio_net_rss_disable(void)
28
} MirrorState;
24
+virtio_net_rss_error(const char *msg, uint32_t value) "%s, value 0x%08x"
29
25
+virtio_net_rss_enable(uint32_t p1, uint16_t p2, uint8_t p3) "hashes 0x%x, table of %d, key of %d"
30
static int filter_send(MirrorState *s,
26
31
const struct iovec *iov,
27
# tulip.c
32
int iovcnt)
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
33
{
29
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
34
+ NetFilterState *nf = NETFILTER(s);
30
index XXXXXXX..XXXXXXX 100644
35
int ret = 0;
31
--- a/hw/net/virtio-net.c
36
ssize_t size = 0;
32
+++ b/hw/net/virtio-net.c
37
uint32_t len = 0;
33
@@ -XXX,XX +XXX,XX @@
38
@@ -XXX,XX +XXX,XX @@ static int filter_send(MirrorState *s,
34
tso/gso/gro 'off'. */
39
goto err;
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;
40
}
73
}
41
74
42
+ if (s->vnet_hdr) {
75
+ virtio_clear_feature(&features, VIRTIO_NET_F_RSS);
43
+ /*
76
features = vhost_net_get_features(get_vhost_net(nc->peer), features);
44
+ * If vnet_hdr = on, we send vnet header len to make other
77
vdev->backend_features = features;
45
+ * module(like colo-compare) know how to parse net
78
46
+ * packet correctly.
79
@@ -XXX,XX +XXX,XX @@ static void virtio_net_set_features(VirtIODevice *vdev, uint64_t features)
47
+ */
48
+ ssize_t vnet_hdr_len;
49
+
50
+ vnet_hdr_len = nf->netdev->vnet_hdr_len;
51
+
52
+ len = htonl(vnet_hdr_len);
53
+ ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len));
54
+ if (ret != sizeof(len)) {
55
+ goto err;
56
+ }
57
+ }
58
+
59
buf = g_malloc(size);
60
iov_to_buf(iov, iovcnt, 0, buf, size);
61
ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)buf, size);
62
@@ -XXX,XX +XXX,XX @@ static void filter_redirector_setup(NetFilterState *nf, Error **errp)
63
}
64
}
80
}
65
81
66
- net_socket_rs_init(&s->rs, redirector_rs_finalize, false);
82
virtio_net_set_multiqueue(n,
67
+ net_socket_rs_init(&s->rs, redirector_rs_finalize, s->vnet_hdr);
83
+ virtio_has_feature(features, VIRTIO_NET_F_RSS) ||
68
84
virtio_has_feature(features, VIRTIO_NET_F_MQ));
69
if (s->indev) {
85
70
chr = qemu_chr_find(s->indev);
86
virtio_net_set_mrg_rx_bufs(n,
71
@@ -XXX,XX +XXX,XX @@ static void filter_mirror_set_outdev(Object *obj,
87
@@ -XXX,XX +XXX,XX @@ static int virtio_net_handle_announce(VirtIONet *n, uint8_t cmd,
72
}
88
}
73
}
89
}
74
90
75
+static bool filter_mirror_get_vnet_hdr(Object *obj, Error **errp)
91
+static void virtio_net_disable_rss(VirtIONet *n)
76
+{
92
+{
77
+ MirrorState *s = FILTER_MIRROR(obj);
93
+ if (n->rss_data.enabled) {
78
+
94
+ trace_virtio_net_rss_disable();
79
+ return s->vnet_hdr;
95
+ }
96
+ n->rss_data.enabled = false;
80
+}
97
+}
81
+
98
+
82
+static void filter_mirror_set_vnet_hdr(Object *obj, bool value, Error **errp)
99
+static uint16_t virtio_net_handle_rss(VirtIONet *n,
100
+ struct iovec *iov, unsigned int iov_cnt)
83
+{
101
+{
84
+ MirrorState *s = FILTER_MIRROR(obj);
102
+ VirtIODevice *vdev = VIRTIO_DEVICE(n);
85
+
103
+ struct virtio_net_rss_config cfg;
86
+ s->vnet_hdr = value;
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;
87
+}
210
+}
88
+
211
+
89
static char *filter_redirector_get_outdev(Object *obj, Error **errp)
212
static int virtio_net_handle_mq(VirtIONet *n, uint8_t cmd,
213
struct iovec *iov, unsigned int iov_cnt)
90
{
214
{
91
MirrorState *s = FILTER_REDIRECTOR(obj);
215
VirtIODevice *vdev = VIRTIO_DEVICE(n);
92
@@ -XXX,XX +XXX,XX @@ static void filter_redirector_set_outdev(Object *obj,
216
- struct virtio_net_ctrl_mq mq;
93
217
- size_t s;
94
static void filter_mirror_init(Object *obj)
218
uint16_t queues;
95
{
219
96
+ MirrorState *s = FILTER_MIRROR(obj);
220
- s = iov_to_buf(iov, iov_cnt, 0, &mq, sizeof(mq));
97
+
221
- if (s != sizeof(mq)) {
98
object_property_add_str(obj, "outdev", filter_mirror_get_outdev,
222
- return VIRTIO_NET_ERR;
99
filter_mirror_set_outdev, NULL);
223
- }
100
+
224
+ virtio_net_disable_rss(n);
101
+ s->vnet_hdr = false;
225
+ if (cmd == VIRTIO_NET_CTRL_MQ_RSS_CONFIG) {
102
+ object_property_add_bool(obj, "vnet_hdr_support",
226
+ queues = virtio_net_handle_rss(n, iov, iov_cnt);
103
+ filter_mirror_get_vnet_hdr,
227
+ } else if (cmd == VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET) {
104
+ filter_mirror_set_vnet_hdr, NULL);
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);
105
}
255
}
106
256
107
static void filter_redirector_init(Object *obj)
257
@@ -XXX,XX +XXX,XX @@ static Property virtio_net_properties[] = {
108
diff --git a/qemu-options.hx b/qemu-options.hx
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
109
index XXXXXXX..XXXXXXX 100644
267
index XXXXXXX..XXXXXXX 100644
110
--- a/qemu-options.hx
268
--- a/include/hw/virtio/virtio-net.h
111
+++ b/qemu-options.hx
269
+++ b/include/hw/virtio/virtio-net.h
112
@@ -XXX,XX +XXX,XX @@ queue @var{all|rx|tx} is an option that can be applied to any netfilter.
270
@@ -XXX,XX +XXX,XX @@ typedef struct VirtioNetRscChain {
113
@option{tx}: the filter is attached to the transmit queue of the netdev,
271
/* Maximum packet size we can receive from tap device: header + 64k */
114
where it will receive packets sent by the netdev.
272
#define VIRTIO_NET_MAX_BUFSIZE (sizeof(struct virtio_net_hdr) + (64 * KiB))
115
273
116
-@item -object filter-mirror,id=@var{id},netdev=@var{netdevid},outdev=@var{chardevid}[,queue=@var{all|rx|tx}]
274
+#define VIRTIO_NET_RSS_MAX_KEY_SIZE 40
117
+@item -object filter-mirror,id=@var{id},netdev=@var{netdevid},outdev=@var{chardevid},queue=@var{all|rx|tx}[,vnet_hdr_support]
275
+#define VIRTIO_NET_RSS_MAX_TABLE_LEN 128
118
276
+
119
-filter-mirror on netdev @var{netdevid},mirror net packet to chardev
277
+typedef struct VirtioNetRssData {
120
-@var{chardevid}
278
+ bool enabled;
121
+filter-mirror on netdev @var{netdevid},mirror net packet to chardev@var{chardevid}, if it has the vnet_hdr_support flag, filter-mirror will mirror packet with vnet_hdr_len.
279
+ uint32_t hash_types;
122
280
+ uint8_t key[VIRTIO_NET_RSS_MAX_KEY_SIZE];
123
@item -object filter-redirector,id=@var{id},netdev=@var{netdevid},indev=@var{chardevid},
281
+ uint16_t indirections_len;
124
outdev=@var{chardevid}[,queue=@var{all|rx|tx}]
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,
125
--
297
--
126
2.7.4
298
2.5.0
127
299
128
300
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Yuri Benditovich <yuri.benditovich@daynix.com>
2
2
3
We add the vnet_hdr_support option for filter-redirector, default is disabled.
3
If VIRTIO_NET_F_RSS negotiated and RSS is enabled, process
4
If you use virtio-net-pci net driver or other driver needs vnet_hdr, please enable it.
4
incoming packets, calculate packet's hash and place the
5
Because colo-compare or other modules needs the vnet_hdr_len to parse
5
packet into respective RX virtqueue.
6
packet, we add this new option send the len to others.
7
You can use it for example:
8
-object filter-redirector,id=r0,netdev=hn0,queue=tx,outdev=red0,vnet_hdr_support
9
6
10
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
7
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
9
---
13
net/filter-mirror.c | 23 +++++++++++++++++++++++
10
hw/net/Makefile.objs | 1 +
14
qemu-options.hx | 6 +++---
11
hw/net/virtio-net.c | 88 +++++++++++++++++++++++++++++++++++++++++-
15
2 files changed, 26 insertions(+), 3 deletions(-)
12
include/hw/virtio/virtio-net.h | 1 +
13
3 files changed, 88 insertions(+), 2 deletions(-)
16
14
17
diff --git a/net/filter-mirror.c b/net/filter-mirror.c
15
diff --git a/hw/net/Makefile.objs b/hw/net/Makefile.objs
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/net/filter-mirror.c
17
--- a/hw/net/Makefile.objs
20
+++ b/net/filter-mirror.c
18
+++ b/hw/net/Makefile.objs
21
@@ -XXX,XX +XXX,XX @@ static void filter_redirector_set_outdev(Object *obj,
19
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MILKYMIST) += milkymist-minimac2.o
22
s->outdev = g_strdup(value);
20
obj-$(CONFIG_PSERIES) += spapr_llan.o
21
obj-$(CONFIG_XILINX_ETHLITE) += xilinx_ethlite.o
22
23
+common-obj-$(CONFIG_VIRTIO_NET) += net_rx_pkt.o
24
obj-$(CONFIG_VIRTIO_NET) += virtio-net.o
25
common-obj-$(call land,$(CONFIG_VIRTIO_NET),$(CONFIG_VHOST_NET)) += vhost_net.o
26
common-obj-$(call lnot,$(call land,$(CONFIG_VIRTIO_NET),$(CONFIG_VHOST_NET))) += vhost_net-stub.o
27
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/net/virtio-net.c
30
+++ b/hw/net/virtio-net.c
31
@@ -XXX,XX +XXX,XX @@
32
#include "trace.h"
33
#include "monitor/qdev.h"
34
#include "hw/pci/pci.h"
35
+#include "net_rx_pkt.h"
36
37
#define VIRTIO_NET_VM_VERSION 11
38
39
@@ -XXX,XX +XXX,XX @@ static int receive_filter(VirtIONet *n, const uint8_t *buf, int size)
40
return 0;
23
}
41
}
24
42
25
+static bool filter_redirector_get_vnet_hdr(Object *obj, Error **errp)
43
+static uint8_t virtio_net_get_hash_type(bool isip4,
44
+ bool isip6,
45
+ bool isudp,
46
+ bool istcp,
47
+ uint32_t types)
26
+{
48
+{
27
+ MirrorState *s = FILTER_REDIRECTOR(obj);
49
+ if (isip4) {
50
+ if (istcp && (types & VIRTIO_NET_RSS_HASH_TYPE_TCPv4)) {
51
+ return NetPktRssIpV4Tcp;
52
+ }
53
+ if (isudp && (types & VIRTIO_NET_RSS_HASH_TYPE_UDPv4)) {
54
+ return NetPktRssIpV4Udp;
55
+ }
56
+ if (types & VIRTIO_NET_RSS_HASH_TYPE_IPv4) {
57
+ return NetPktRssIpV4;
58
+ }
59
+ } else if (isip6) {
60
+ uint32_t mask = VIRTIO_NET_RSS_HASH_TYPE_TCP_EX |
61
+ VIRTIO_NET_RSS_HASH_TYPE_TCPv6;
28
+
62
+
29
+ return s->vnet_hdr;
63
+ if (istcp && (types & mask)) {
64
+ return (types & VIRTIO_NET_RSS_HASH_TYPE_TCP_EX) ?
65
+ NetPktRssIpV6TcpEx : NetPktRssIpV6Tcp;
66
+ }
67
+ mask = VIRTIO_NET_RSS_HASH_TYPE_UDP_EX | VIRTIO_NET_RSS_HASH_TYPE_UDPv6;
68
+ if (isudp && (types & mask)) {
69
+ return (types & VIRTIO_NET_RSS_HASH_TYPE_UDP_EX) ?
70
+ NetPktRssIpV6UdpEx : NetPktRssIpV6Udp;
71
+ }
72
+ mask = VIRTIO_NET_RSS_HASH_TYPE_IP_EX | VIRTIO_NET_RSS_HASH_TYPE_IPv6;
73
+ if (types & mask) {
74
+ return (types & VIRTIO_NET_RSS_HASH_TYPE_IP_EX) ?
75
+ NetPktRssIpV6Ex : NetPktRssIpV6;
76
+ }
77
+ }
78
+ return 0xff;
30
+}
79
+}
31
+
80
+
32
+static void filter_redirector_set_vnet_hdr(Object *obj,
81
+static int virtio_net_process_rss(NetClientState *nc, const uint8_t *buf,
33
+ bool value,
82
+ size_t size)
34
+ Error **errp)
35
+{
83
+{
36
+ MirrorState *s = FILTER_REDIRECTOR(obj);
84
+ VirtIONet *n = qemu_get_nic_opaque(nc);
85
+ unsigned int index = nc->queue_index, new_index;
86
+ struct NetRxPkt *pkt = n->rx_pkt;
87
+ uint8_t net_hash_type;
88
+ uint32_t hash;
89
+ bool isip4, isip6, isudp, istcp;
37
+
90
+
38
+ s->vnet_hdr = value;
91
+ net_rx_pkt_set_protocols(pkt, buf + n->host_hdr_len,
92
+ size - n->host_hdr_len);
93
+ net_rx_pkt_get_protocols(pkt, &isip4, &isip6, &isudp, &istcp);
94
+ if (isip4 && (net_rx_pkt_get_ip4_info(pkt)->fragment)) {
95
+ istcp = isudp = false;
96
+ }
97
+ if (isip6 && (net_rx_pkt_get_ip6_info(pkt)->fragment)) {
98
+ istcp = isudp = false;
99
+ }
100
+ net_hash_type = virtio_net_get_hash_type(isip4, isip6, isudp, istcp,
101
+ n->rss_data.hash_types);
102
+ if (net_hash_type > NetPktRssIpV6UdpEx) {
103
+ return n->rss_data.default_queue;
104
+ }
105
+
106
+ hash = net_rx_pkt_calc_rss_hash(pkt, net_hash_type, n->rss_data.key);
107
+ new_index = hash & (n->rss_data.indirections_len - 1);
108
+ new_index = n->rss_data.indirections_table[new_index];
109
+ if (index == new_index) {
110
+ return -1;
111
+ }
112
+ return new_index;
39
+}
113
+}
40
+
114
+
41
static void filter_mirror_init(Object *obj)
115
static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
116
- size_t size)
117
+ size_t size, bool no_rss)
42
{
118
{
43
MirrorState *s = FILTER_MIRROR(obj);
119
VirtIONet *n = qemu_get_nic_opaque(nc);
44
@@ -XXX,XX +XXX,XX @@ static void filter_mirror_init(Object *obj)
120
VirtIONetQueue *q = virtio_net_get_subqueue(nc);
45
121
@@ -XXX,XX +XXX,XX @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
46
static void filter_redirector_init(Object *obj)
122
return -1;
123
}
124
125
+ if (!no_rss && n->rss_data.enabled) {
126
+ int index = virtio_net_process_rss(nc, buf, size);
127
+ if (index >= 0) {
128
+ NetClientState *nc2 = qemu_get_subqueue(n->nic, index);
129
+ return virtio_net_receive_rcu(nc2, buf, size, true);
130
+ }
131
+ }
132
+
133
/* hdr_len refers to the header we supply to the guest */
134
if (!virtio_net_has_buffers(q, size + n->guest_hdr_len - n->host_hdr_len)) {
135
return 0;
136
@@ -XXX,XX +XXX,XX @@ static ssize_t virtio_net_do_receive(NetClientState *nc, const uint8_t *buf,
47
{
137
{
48
+ MirrorState *s = FILTER_REDIRECTOR(obj);
138
RCU_READ_LOCK_GUARD();
139
140
- return virtio_net_receive_rcu(nc, buf, size);
141
+ return virtio_net_receive_rcu(nc, buf, size, false);
142
}
143
144
static void virtio_net_rsc_extract_unit4(VirtioNetRscChain *chain,
145
@@ -XXX,XX +XXX,XX @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
146
147
QTAILQ_INIT(&n->rsc_chains);
148
n->qdev = dev;
49
+
149
+
50
object_property_add_str(obj, "indev", filter_redirector_get_indev,
150
+ net_rx_pkt_init(&n->rx_pkt, false);
51
filter_redirector_set_indev, NULL);
52
object_property_add_str(obj, "outdev", filter_redirector_get_outdev,
53
filter_redirector_set_outdev, NULL);
54
+
55
+ s->vnet_hdr = false;
56
+ object_property_add_bool(obj, "vnet_hdr_support",
57
+ filter_redirector_get_vnet_hdr,
58
+ filter_redirector_set_vnet_hdr, NULL);
59
}
151
}
60
152
61
static void filter_mirror_fini(Object *obj)
153
static void virtio_net_device_unrealize(DeviceState *dev)
62
diff --git a/qemu-options.hx b/qemu-options.hx
154
@@ -XXX,XX +XXX,XX @@ static void virtio_net_device_unrealize(DeviceState *dev)
155
qemu_del_nic(n->nic);
156
virtio_net_rsc_cleanup(n);
157
g_free(n->rss_data.indirections_table);
158
+ net_rx_pkt_uninit(n->rx_pkt);
159
virtio_cleanup(vdev);
160
}
161
162
diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
63
index XXXXXXX..XXXXXXX 100644
163
index XXXXXXX..XXXXXXX 100644
64
--- a/qemu-options.hx
164
--- a/include/hw/virtio/virtio-net.h
65
+++ b/qemu-options.hx
165
+++ b/include/hw/virtio/virtio-net.h
66
@@ -XXX,XX +XXX,XX @@ queue @var{all|rx|tx} is an option that can be applied to any netfilter.
166
@@ -XXX,XX +XXX,XX @@ struct VirtIONet {
67
167
DeviceListener primary_listener;
68
filter-mirror on netdev @var{netdevid},mirror net packet to chardev@var{chardevid}, if it has the vnet_hdr_support flag, filter-mirror will mirror packet with vnet_hdr_len.
168
Notifier migration_state;
69
169
VirtioNetRssData rss_data;
70
-@item -object filter-redirector,id=@var{id},netdev=@var{netdevid},indev=@var{chardevid},
170
+ struct NetRxPkt *rx_pkt;
71
-outdev=@var{chardevid}[,queue=@var{all|rx|tx}]
171
};
72
+@item -object filter-redirector,id=@var{id},netdev=@var{netdevid},indev=@var{chardevid},outdev=@var{chardevid},queue=@var{all|rx|tx}[,vnet_hdr_support]
172
73
173
void virtio_net_set_netclient_name(VirtIONet *n, const char *name,
74
filter-redirector on netdev @var{netdevid},redirect filter's net packet to chardev
75
-@var{chardevid},and redirect indev's packet to filter.
76
+@var{chardevid},and redirect indev's packet to filter.if it has the vnet_hdr_support flag,
77
+filter-redirector will redirect packet with vnet_hdr_len.
78
Create a filter-redirector we need to differ outdev id from indev id, id can not
79
be the same. we can just use indev or outdev, but at least one of indev or outdev
80
need to be specified.
81
--
174
--
82
2.7.4
175
2.5.0
83
176
84
177
diff view generated by jsdifflib
New patch
1
From: Yuri Benditovich <yuri.benditovich@daynix.com>
1
2
3
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
4
Signed-off-by: Jason Wang <jasowang@redhat.com>
5
---
6
net/tap.c | 3 ++-
7
1 file changed, 2 insertions(+), 1 deletion(-)
8
9
diff --git a/net/tap.c b/net/tap.c
10
index XXXXXXX..XXXXXXX 100644
11
--- a/net/tap.c
12
+++ b/net/tap.c
13
@@ -XXX,XX +XXX,XX @@ static void tap_set_vnet_hdr_len(NetClientState *nc, int len)
14
15
assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
16
assert(len == sizeof(struct virtio_net_hdr_mrg_rxbuf) ||
17
- len == sizeof(struct virtio_net_hdr));
18
+ len == sizeof(struct virtio_net_hdr) ||
19
+ len == sizeof(struct virtio_net_hdr_v1_hash));
20
21
tap_fd_set_vnet_hdr_len(s->fd, len);
22
s->host_vnet_hdr_len = len;
23
--
24
2.5.0
25
26
diff view generated by jsdifflib
New patch
1
1
From: Yuri Benditovich <yuri.benditovich@daynix.com>
2
3
Suggest VIRTIO_NET_F_HASH_REPORT if specified in device
4
parameters.
5
If the VIRTIO_NET_F_HASH_REPORT is set,
6
the device extends configuration space. If the feature
7
is negotiated, the packet layout is extended to
8
accomodate the hash information. In this case deliver
9
packet's hash value and report type in virtio header
10
extension.
11
Use for configuration the same procedure as already
12
used for RSS. We add two fields in rss_data that
13
controls what the device does with the calculated hash
14
if rss_data.enabled is set. If field 'populate' is set
15
the hash is set in the packet, if field 'redirect' is
16
set the hash is used to decide the queue to place the
17
packet to.
18
19
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
20
Signed-off-by: Jason Wang <jasowang@redhat.com>
21
---
22
hw/net/virtio-net.c | 99 +++++++++++++++++++++++++++++++++---------
23
include/hw/virtio/virtio-net.h | 2 +
24
2 files changed, 81 insertions(+), 20 deletions(-)
25
26
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/net/virtio-net.c
29
+++ b/hw/net/virtio-net.c
30
@@ -XXX,XX +XXX,XX @@ static VirtIOFeature feature_sizes[] = {
31
.end = endof(struct virtio_net_config, mtu)},
32
{.flags = 1ULL << VIRTIO_NET_F_SPEED_DUPLEX,
33
.end = endof(struct virtio_net_config, duplex)},
34
- {.flags = 1ULL << VIRTIO_NET_F_RSS,
35
+ {.flags = (1ULL << VIRTIO_NET_F_RSS) | (1ULL << VIRTIO_NET_F_HASH_REPORT),
36
.end = endof(struct virtio_net_config, supported_hash_types)},
37
{}
38
};
39
@@ -XXX,XX +XXX,XX @@ static void virtio_net_get_config(VirtIODevice *vdev, uint8_t *config)
40
netcfg.duplex = n->net_conf.duplex;
41
netcfg.rss_max_key_size = VIRTIO_NET_RSS_MAX_KEY_SIZE;
42
virtio_stw_p(vdev, &netcfg.rss_max_indirection_table_length,
43
- VIRTIO_NET_RSS_MAX_TABLE_LEN);
44
+ virtio_host_has_feature(vdev, VIRTIO_NET_F_RSS) ?
45
+ VIRTIO_NET_RSS_MAX_TABLE_LEN : 1);
46
virtio_stl_p(vdev, &netcfg.supported_hash_types,
47
VIRTIO_NET_RSS_SUPPORTED_HASHES);
48
memcpy(config, &netcfg, n->config_size);
49
@@ -XXX,XX +XXX,XX @@ static int peer_has_ufo(VirtIONet *n)
50
}
51
52
static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs,
53
- int version_1)
54
+ int version_1, int hash_report)
55
{
56
int i;
57
NetClientState *nc;
58
@@ -XXX,XX +XXX,XX @@ static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs,
59
n->mergeable_rx_bufs = mergeable_rx_bufs;
60
61
if (version_1) {
62
- n->guest_hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf);
63
+ n->guest_hdr_len = hash_report ?
64
+ sizeof(struct virtio_net_hdr_v1_hash) :
65
+ sizeof(struct virtio_net_hdr_mrg_rxbuf);
66
+ n->rss_data.populate_hash = !!hash_report;
67
} else {
68
n->guest_hdr_len = n->mergeable_rx_bufs ?
69
sizeof(struct virtio_net_hdr_mrg_rxbuf) :
70
@@ -XXX,XX +XXX,XX @@ static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features,
71
virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_TSO4);
72
virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_TSO6);
73
virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_ECN);
74
+
75
+ virtio_clear_feature(&features, VIRTIO_NET_F_HASH_REPORT);
76
}
77
78
if (!peer_has_vnet_hdr(n) || !peer_has_ufo(n)) {
79
@@ -XXX,XX +XXX,XX @@ static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features,
80
}
81
82
virtio_clear_feature(&features, VIRTIO_NET_F_RSS);
83
+ virtio_clear_feature(&features, VIRTIO_NET_F_HASH_REPORT);
84
features = vhost_net_get_features(get_vhost_net(nc->peer), features);
85
vdev->backend_features = features;
86
87
@@ -XXX,XX +XXX,XX @@ static void virtio_net_set_features(VirtIODevice *vdev, uint64_t features)
88
virtio_has_feature(features,
89
VIRTIO_NET_F_MRG_RXBUF),
90
virtio_has_feature(features,
91
- VIRTIO_F_VERSION_1));
92
+ VIRTIO_F_VERSION_1),
93
+ virtio_has_feature(features,
94
+ VIRTIO_NET_F_HASH_REPORT));
95
96
n->rsc4_enabled = virtio_has_feature(features, VIRTIO_NET_F_RSC_EXT) &&
97
virtio_has_feature(features, VIRTIO_NET_F_GUEST_TSO4);
98
n->rsc6_enabled = virtio_has_feature(features, VIRTIO_NET_F_RSC_EXT) &&
99
virtio_has_feature(features, VIRTIO_NET_F_GUEST_TSO6);
100
+ n->rss_data.redirect = virtio_has_feature(features, VIRTIO_NET_F_RSS);
101
102
if (n->has_vnet_hdr) {
103
n->curr_guest_offloads =
104
@@ -XXX,XX +XXX,XX @@ static void virtio_net_disable_rss(VirtIONet *n)
105
}
106
107
static uint16_t virtio_net_handle_rss(VirtIONet *n,
108
- struct iovec *iov, unsigned int iov_cnt)
109
+ struct iovec *iov,
110
+ unsigned int iov_cnt,
111
+ bool do_rss)
112
{
113
VirtIODevice *vdev = VIRTIO_DEVICE(n);
114
struct virtio_net_rss_config cfg;
115
@@ -XXX,XX +XXX,XX @@ static uint16_t virtio_net_handle_rss(VirtIONet *n,
116
const char *err_msg = "";
117
uint32_t err_value = 0;
118
119
- if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_RSS)) {
120
+ if (do_rss && !virtio_vdev_has_feature(vdev, VIRTIO_NET_F_RSS)) {
121
err_msg = "RSS is not negotiated";
122
goto error;
123
}
124
+ if (!do_rss && !virtio_vdev_has_feature(vdev, VIRTIO_NET_F_HASH_REPORT)) {
125
+ err_msg = "Hash report is not negotiated";
126
+ goto error;
127
+ }
128
size_get = offsetof(struct virtio_net_rss_config, indirection_table);
129
s = iov_to_buf(iov, iov_cnt, offset, &cfg, size_get);
130
if (s != size_get) {
131
@@ -XXX,XX +XXX,XX @@ static uint16_t virtio_net_handle_rss(VirtIONet *n,
132
n->rss_data.indirections_len =
133
virtio_lduw_p(vdev, &cfg.indirection_table_mask);
134
n->rss_data.indirections_len++;
135
+ if (!do_rss) {
136
+ n->rss_data.indirections_len = 1;
137
+ }
138
if (!is_power_of_2(n->rss_data.indirections_len)) {
139
err_msg = "Invalid size of indirection table";
140
err_value = n->rss_data.indirections_len;
141
@@ -XXX,XX +XXX,XX @@ static uint16_t virtio_net_handle_rss(VirtIONet *n,
142
err_value = n->rss_data.indirections_len;
143
goto error;
144
}
145
- n->rss_data.default_queue =
146
- virtio_lduw_p(vdev, &cfg.unclassified_queue);
147
+ n->rss_data.default_queue = do_rss ?
148
+ virtio_lduw_p(vdev, &cfg.unclassified_queue) : 0;
149
if (n->rss_data.default_queue >= n->max_queues) {
150
err_msg = "Invalid default queue";
151
err_value = n->rss_data.default_queue;
152
@@ -XXX,XX +XXX,XX @@ static uint16_t virtio_net_handle_rss(VirtIONet *n,
153
err_value = (uint32_t)s;
154
goto error;
155
}
156
- queues = virtio_lduw_p(vdev, &temp.us);
157
+ queues = do_rss ? virtio_lduw_p(vdev, &temp.us) : n->curr_queues;
158
if (queues == 0 || queues > n->max_queues) {
159
err_msg = "Invalid number of queues";
160
err_value = queues;
161
@@ -XXX,XX +XXX,XX @@ static int virtio_net_handle_mq(VirtIONet *n, uint8_t cmd,
162
uint16_t queues;
163
164
virtio_net_disable_rss(n);
165
+ if (cmd == VIRTIO_NET_CTRL_MQ_HASH_CONFIG) {
166
+ queues = virtio_net_handle_rss(n, iov, iov_cnt, false);
167
+ return queues ? VIRTIO_NET_OK : VIRTIO_NET_ERR;
168
+ }
169
if (cmd == VIRTIO_NET_CTRL_MQ_RSS_CONFIG) {
170
- queues = virtio_net_handle_rss(n, iov, iov_cnt);
171
+ queues = virtio_net_handle_rss(n, iov, iov_cnt, true);
172
} else if (cmd == VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET) {
173
struct virtio_net_ctrl_mq mq;
174
size_t s;
175
@@ -XXX,XX +XXX,XX @@ static uint8_t virtio_net_get_hash_type(bool isip4,
176
return 0xff;
177
}
178
179
+static void virtio_set_packet_hash(const uint8_t *buf, uint8_t report,
180
+ uint32_t hash)
181
+{
182
+ struct virtio_net_hdr_v1_hash *hdr = (void *)buf;
183
+ hdr->hash_value = hash;
184
+ hdr->hash_report = report;
185
+}
186
+
187
static int virtio_net_process_rss(NetClientState *nc, const uint8_t *buf,
188
size_t size)
189
{
190
VirtIONet *n = qemu_get_nic_opaque(nc);
191
- unsigned int index = nc->queue_index, new_index;
192
+ unsigned int index = nc->queue_index, new_index = index;
193
struct NetRxPkt *pkt = n->rx_pkt;
194
uint8_t net_hash_type;
195
uint32_t hash;
196
bool isip4, isip6, isudp, istcp;
197
+ static const uint8_t reports[NetPktRssIpV6UdpEx + 1] = {
198
+ VIRTIO_NET_HASH_REPORT_IPv4,
199
+ VIRTIO_NET_HASH_REPORT_TCPv4,
200
+ VIRTIO_NET_HASH_REPORT_TCPv6,
201
+ VIRTIO_NET_HASH_REPORT_IPv6,
202
+ VIRTIO_NET_HASH_REPORT_IPv6_EX,
203
+ VIRTIO_NET_HASH_REPORT_TCPv6_EX,
204
+ VIRTIO_NET_HASH_REPORT_UDPv4,
205
+ VIRTIO_NET_HASH_REPORT_UDPv6,
206
+ VIRTIO_NET_HASH_REPORT_UDPv6_EX
207
+ };
208
209
net_rx_pkt_set_protocols(pkt, buf + n->host_hdr_len,
210
size - n->host_hdr_len);
211
@@ -XXX,XX +XXX,XX @@ static int virtio_net_process_rss(NetClientState *nc, const uint8_t *buf,
212
net_hash_type = virtio_net_get_hash_type(isip4, isip6, isudp, istcp,
213
n->rss_data.hash_types);
214
if (net_hash_type > NetPktRssIpV6UdpEx) {
215
- return n->rss_data.default_queue;
216
+ if (n->rss_data.populate_hash) {
217
+ virtio_set_packet_hash(buf, VIRTIO_NET_HASH_REPORT_NONE, 0);
218
+ }
219
+ return n->rss_data.redirect ? n->rss_data.default_queue : -1;
220
}
221
222
hash = net_rx_pkt_calc_rss_hash(pkt, net_hash_type, n->rss_data.key);
223
- new_index = hash & (n->rss_data.indirections_len - 1);
224
- new_index = n->rss_data.indirections_table[new_index];
225
- if (index == new_index) {
226
- return -1;
227
+
228
+ if (n->rss_data.populate_hash) {
229
+ virtio_set_packet_hash(buf, reports[net_hash_type], hash);
230
}
231
- return new_index;
232
+
233
+ if (n->rss_data.redirect) {
234
+ new_index = hash & (n->rss_data.indirections_len - 1);
235
+ new_index = n->rss_data.indirections_table[new_index];
236
+ }
237
+
238
+ return (index == new_index) ? -1 : new_index;
239
}
240
241
static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
242
@@ -XXX,XX +XXX,XX @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
243
}
244
245
receive_header(n, sg, elem->in_num, buf, size);
246
+ if (n->rss_data.populate_hash) {
247
+ offset = sizeof(mhdr);
248
+ iov_from_buf(sg, elem->in_num, offset,
249
+ buf + offset, n->host_hdr_len - sizeof(mhdr));
250
+ }
251
offset = n->host_hdr_len;
252
total += n->guest_hdr_len;
253
guest_offset = n->guest_hdr_len;
254
@@ -XXX,XX +XXX,XX @@ static int virtio_net_post_load_device(void *opaque, int version_id)
255
trace_virtio_net_post_load_device();
256
virtio_net_set_mrg_rx_bufs(n, n->mergeable_rx_bufs,
257
virtio_vdev_has_feature(vdev,
258
- VIRTIO_F_VERSION_1));
259
+ VIRTIO_F_VERSION_1),
260
+ virtio_vdev_has_feature(vdev,
261
+ VIRTIO_NET_F_HASH_REPORT));
262
263
/* MAC_TABLE_ENTRIES may be different from the saved image */
264
if (n->mac_table.in_use > MAC_TABLE_ENTRIES) {
265
@@ -XXX,XX +XXX,XX @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
266
267
n->vqs[0].tx_waiting = 0;
268
n->tx_burst = n->net_conf.txburst;
269
- virtio_net_set_mrg_rx_bufs(n, 0, 0);
270
+ virtio_net_set_mrg_rx_bufs(n, 0, 0, 0);
271
n->promisc = 1; /* for compatibility */
272
273
n->mac_table.macs = g_malloc0(MAC_TABLE_ENTRIES * ETH_ALEN);
274
@@ -XXX,XX +XXX,XX @@ static Property virtio_net_properties[] = {
275
DEFINE_PROP_BIT64("mq", VirtIONet, host_features, VIRTIO_NET_F_MQ, false),
276
DEFINE_PROP_BIT64("rss", VirtIONet, host_features,
277
VIRTIO_NET_F_RSS, false),
278
+ DEFINE_PROP_BIT64("hash", VirtIONet, host_features,
279
+ VIRTIO_NET_F_HASH_REPORT, false),
280
DEFINE_PROP_BIT64("guest_rsc_ext", VirtIONet, host_features,
281
VIRTIO_NET_F_RSC_EXT, false),
282
DEFINE_PROP_UINT32("rsc_interval", VirtIONet, rsc_timeout,
283
diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
284
index XXXXXXX..XXXXXXX 100644
285
--- a/include/hw/virtio/virtio-net.h
286
+++ b/include/hw/virtio/virtio-net.h
287
@@ -XXX,XX +XXX,XX @@ typedef struct VirtioNetRscChain {
288
289
typedef struct VirtioNetRssData {
290
bool enabled;
291
+ bool redirect;
292
+ bool populate_hash;
293
uint32_t hash_types;
294
uint8_t key[VIRTIO_NET_RSS_MAX_KEY_SIZE];
295
uint16_t indirections_len;
296
--
297
2.5.0
298
299
diff view generated by jsdifflib
New patch
1
From: Yuri Benditovich <yuri.benditovich@daynix.com>
1
2
3
Similar to VMSTATE_VARRAY_UINT32_ALLOC, but the size is
4
16-bit field.
5
6
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
7
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
10
include/migration/vmstate.h | 10 ++++++++++
11
1 file changed, 10 insertions(+)
12
13
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/migration/vmstate.h
16
+++ b/include/migration/vmstate.h
17
@@ -XXX,XX +XXX,XX @@ extern const VMStateInfo vmstate_info_qlist;
18
.offset = vmstate_offset_pointer(_state, _field, _type), \
19
}
20
21
+#define VMSTATE_VARRAY_UINT16_ALLOC(_field, _state, _field_num, _version, _info, _type) {\
22
+ .name = (stringify(_field)), \
23
+ .version_id = (_version), \
24
+ .num_offset = vmstate_offset_value(_state, _field_num, uint16_t),\
25
+ .info = &(_info), \
26
+ .size = sizeof(_type), \
27
+ .flags = VMS_VARRAY_UINT16 | VMS_POINTER | VMS_ALLOC, \
28
+ .offset = vmstate_offset_pointer(_state, _field, _type), \
29
+}
30
+
31
#define VMSTATE_VARRAY_UINT16_UNSAFE(_field, _state, _field_num, _version, _info, _type) {\
32
.name = (stringify(_field)), \
33
.version_id = (_version), \
34
--
35
2.5.0
36
37
diff view generated by jsdifflib
1
From: Michal Privoznik <mprivozn@redhat.com>
1
From: Yuri Benditovich <yuri.benditovich@daynix.com>
2
2
3
We have a function that checks if given number is power of two.
3
Save and restore RSS/hash report configuration.
4
We should prefer it instead of expanding the check on our own.
5
4
6
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
5
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
7
---
9
hw/net/virtio-net.c | 2 +-
8
hw/net/virtio-net.c | 37 +++++++++++++++++++++++++++++++++++++
10
1 file changed, 1 insertion(+), 1 deletion(-)
9
1 file changed, 37 insertions(+)
11
10
12
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
11
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
13
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/net/virtio-net.c
13
--- a/hw/net/virtio-net.c
15
+++ b/hw/net/virtio-net.c
14
+++ b/hw/net/virtio-net.c
16
@@ -XXX,XX +XXX,XX @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
15
@@ -XXX,XX +XXX,XX @@ static int virtio_net_post_load_device(void *opaque, int version_id)
17
*/
16
}
18
if (n->net_conf.rx_queue_size < VIRTIO_NET_RX_QUEUE_MIN_SIZE ||
17
}
19
n->net_conf.rx_queue_size > VIRTQUEUE_MAX_SIZE ||
18
20
- (n->net_conf.rx_queue_size & (n->net_conf.rx_queue_size - 1))) {
19
+ if (n->rss_data.enabled) {
21
+ !is_power_of_2(n->net_conf.rx_queue_size)) {
20
+ trace_virtio_net_rss_enable(n->rss_data.hash_types,
22
error_setg(errp, "Invalid rx_queue_size (= %" PRIu16 "), "
21
+ n->rss_data.indirections_len,
23
"must be a power of 2 between %d and %d.",
22
+ sizeof(n->rss_data.key));
24
n->net_conf.rx_queue_size, VIRTIO_NET_RX_QUEUE_MIN_SIZE,
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 = {
25
--
73
--
26
2.7.4
74
2.5.0
27
75
28
76
diff view generated by jsdifflib
1
Spec said offloads should be le64, so use virtio_ldq_p() to guarantee
1
From: Yuri Benditovich <yuri.benditovich@daynix.com>
2
valid endian.
3
2
4
Fixes: 644c98587d4c ("virtio-net: dynamic network offloads configuration")
3
Removal of duplicated RSC definitions. Changing names of the
5
Cc: qemu-stable@nongnu.org
4
fields to ones defined in the Linux header.
6
Cc: Dmitry Fleytman <dfleytma@redhat.com>
5
6
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
8
---
9
hw/net/virtio-net.c | 2 ++
9
hw/net/virtio-net.c | 28 ++++------------------------
10
1 file changed, 2 insertions(+)
10
1 file changed, 4 insertions(+), 24 deletions(-)
11
11
12
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
12
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
13
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/net/virtio-net.c
14
--- a/hw/net/virtio-net.c
15
+++ b/hw/net/virtio-net.c
15
+++ b/hw/net/virtio-net.c
16
@@ -XXX,XX +XXX,XX @@ static int virtio_net_handle_offloads(VirtIONet *n, uint8_t cmd,
16
@@ -XXX,XX +XXX,XX @@
17
if (cmd == VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET) {
17
VIRTIO_NET_RSS_HASH_TYPE_TCP_EX | \
18
uint64_t supported_offloads;
18
VIRTIO_NET_RSS_HASH_TYPE_UDP_EX)
19
19
20
+ offloads = virtio_ldq_p(vdev, &offloads);
20
-/* temporary until standard header include it */
21
+
21
-#if !defined(VIRTIO_NET_HDR_F_RSC_INFO)
22
if (!n->has_vnet_hdr) {
22
-
23
return VIRTIO_NET_ERR;
23
-#define VIRTIO_NET_HDR_F_RSC_INFO 4 /* rsc_ext data in csum_ fields */
24
}
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;
25
--
63
--
26
2.7.4
64
2.5.0
27
65
28
66
diff view generated by jsdifflib
New patch
1
From: Helge Deller <deller@gmx.de>
1
2
3
The tulip network driver in a qemu-system-hppa emulation is broken in
4
the sense that bigger network packages aren't received any longer and
5
thus even running e.g. "apt update" inside the VM fails.
6
7
The breakage was introduced by commit 8ffb7265af ("check frame size and
8
r/w data length") which added checks to prevent accesses outside of the
9
rx/tx buffers.
10
11
But the new checks were implemented wrong. The variable rx_frame_len
12
counts backwards, from rx_frame_size down to zero, and the variable len
13
is never bigger than rx_frame_len, so accesses just can't happen and the
14
checks are unnecessary.
15
On the contrary the checks now prevented bigger packages to be moved
16
into the rx buffers.
17
18
This patch reverts the wrong checks and were sucessfully tested with a
19
qemu-system-hppa emulation.
20
21
Fixes: 8ffb7265af ("check frame size and r/w data length")
22
Buglink: https://bugs.launchpad.net/bugs/1874539
23
Signed-off-by: Helge Deller <deller@gmx.de>
24
Signed-off-by: Jason Wang <jasowang@redhat.com>
25
---
26
hw/net/tulip.c | 6 ------
27
1 file changed, 6 deletions(-)
28
29
diff --git a/hw/net/tulip.c b/hw/net/tulip.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/net/tulip.c
32
+++ b/hw/net/tulip.c
33
@@ -XXX,XX +XXX,XX @@ static void tulip_copy_rx_bytes(TULIPState *s, struct tulip_descriptor *desc)
34
len = s->rx_frame_len;
35
}
36
37
- if (s->rx_frame_len + len > sizeof(s->rx_frame)) {
38
- return;
39
- }
40
pci_dma_write(&s->dev, desc->buf_addr1, s->rx_frame +
41
(s->rx_frame_size - s->rx_frame_len), len);
42
s->rx_frame_len -= len;
43
@@ -XXX,XX +XXX,XX @@ static void tulip_copy_rx_bytes(TULIPState *s, struct tulip_descriptor *desc)
44
len = s->rx_frame_len;
45
}
46
47
- if (s->rx_frame_len + len > sizeof(s->rx_frame)) {
48
- return;
49
- }
50
pci_dma_write(&s->dev, desc->buf_addr2, s->rx_frame +
51
(s->rx_frame_size - s->rx_frame_len), len);
52
s->rx_frame_len -= len;
53
--
54
2.5.0
55
56
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
Bit #14 is "DE" for 'Descriptor Error':
4
5
When set, indicates a frame truncation caused by a frame
6
that does not fit within the current descriptor buffers,
7
and that the 21143 does not own the next descriptor.
8
9
[Table 4-1. RDES0 Bit Fields Description]
10
11
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
---
14
hw/net/tulip.h | 2 +-
15
1 file changed, 1 insertion(+), 1 deletion(-)
16
17
diff --git a/hw/net/tulip.h b/hw/net/tulip.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/net/tulip.h
20
+++ b/hw/net/tulip.h
21
@@ -XXX,XX +XXX,XX @@
22
#define RDES0_RF BIT(11)
23
#define RDES0_DT_SHIFT 12
24
#define RDES0_DT_MASK 3
25
-#define RDES0_LE BIT(14)
26
+#define RDES0_DE BIT(14)
27
#define RDES0_ES BIT(15)
28
#define RDES0_FL_SHIFT 16
29
#define RDES0_FL_MASK 0x3fff
30
--
31
2.5.0
32
33
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
Log with GUEST_ERROR what the guest is doing wrong.
4
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
---
8
hw/net/tulip.c | 6 ++++++
9
1 file changed, 6 insertions(+)
10
11
diff --git a/hw/net/tulip.c b/hw/net/tulip.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/net/tulip.c
14
+++ b/hw/net/tulip.c
15
@@ -XXX,XX +XXX,XX @@ static int tulip_copy_tx_buffers(TULIPState *s, struct tulip_descriptor *desc)
16
int len2 = (desc->control >> TDES1_BUF2_SIZE_SHIFT) & TDES1_BUF2_SIZE_MASK;
17
18
if (s->tx_frame_len + len1 > sizeof(s->tx_frame)) {
19
+ qemu_log_mask(LOG_GUEST_ERROR,
20
+ "%s: descriptor overflow (ofs: %u, len:%d, size:%zu)\n",
21
+ __func__, s->tx_frame_len, len1, sizeof(s->tx_frame));
22
return -1;
23
}
24
if (len1) {
25
@@ -XXX,XX +XXX,XX @@ static int tulip_copy_tx_buffers(TULIPState *s, struct tulip_descriptor *desc)
26
}
27
28
if (s->tx_frame_len + len2 > sizeof(s->tx_frame)) {
29
+ qemu_log_mask(LOG_GUEST_ERROR,
30
+ "%s: descriptor overflow (ofs: %u, len:%d, size:%zu)\n",
31
+ __func__, s->tx_frame_len, len2, sizeof(s->tx_frame));
32
return -1;
33
}
34
if (len2) {
35
--
36
2.5.0
37
38
diff view generated by jsdifflib
New patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
1
2
3
Enabling debug breaks the build, Fix them and make debug statements
4
always compilable. Fix few statements to use sized integer casting.
5
6
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
7
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
10
hw/net/cadence_gem.c | 27 +++++++++++++--------------
11
1 file changed, 13 insertions(+), 14 deletions(-)
12
13
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/net/cadence_gem.c
16
+++ b/hw/net/cadence_gem.c
17
@@ -XXX,XX +XXX,XX @@
18
#include "sysemu/dma.h"
19
#include "net/checksum.h"
20
21
-#ifdef CADENCE_GEM_ERR_DEBUG
22
-#define DB_PRINT(...) do { \
23
- fprintf(stderr, ": %s: ", __func__); \
24
- fprintf(stderr, ## __VA_ARGS__); \
25
- } while (0)
26
-#else
27
- #define DB_PRINT(...)
28
-#endif
29
+#define CADENCE_GEM_ERR_DEBUG 0
30
+#define DB_PRINT(...) do {\
31
+ if (CADENCE_GEM_ERR_DEBUG) { \
32
+ qemu_log(": %s: ", __func__); \
33
+ qemu_log(__VA_ARGS__); \
34
+ } \
35
+} while (0)
36
37
#define GEM_NWCTRL (0x00000000/4) /* Network Control reg */
38
#define GEM_NWCFG (0x00000004/4) /* Network Config reg */
39
@@ -XXX,XX +XXX,XX @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
40
size += 4;
41
}
42
43
- DB_PRINT("config bufsize: %d packet size: %ld\n", rxbufsize, size);
44
+ DB_PRINT("config bufsize: %u packet size: %zd\n", rxbufsize, size);
45
46
/* Find which queue we are targeting */
47
q = get_queue_from_screen(s, rxbuf_ptr, rxbufsize);
48
@@ -XXX,XX +XXX,XX @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
49
return -1;
50
}
51
52
- DB_PRINT("copy %u bytes to 0x%" PRIx64 "\n",
53
- MIN(bytes_to_copy, rxbufsize),
54
- rx_desc_get_buffer(s, s->rx_desc[q]));
55
+ DB_PRINT("copy %" PRIu32 " bytes to 0x%" PRIx64 "\n",
56
+ MIN(bytes_to_copy, rxbufsize),
57
+ rx_desc_get_buffer(s, s->rx_desc[q]));
58
59
/* Copy packet data to emulated DMA buffer */
60
address_space_write(&s->dma_as, rx_desc_get_buffer(s, s->rx_desc[q]) +
61
@@ -XXX,XX +XXX,XX @@ static void gem_transmit(CadenceGEMState *s)
62
*/
63
if ((tx_desc_get_buffer(s, desc) == 0) ||
64
(tx_desc_get_length(desc) == 0)) {
65
- DB_PRINT("Invalid TX descriptor @ 0x%x\n",
66
- (unsigned)packet_desc_addr);
67
+ DB_PRINT("Invalid TX descriptor @ 0x%" HWADDR_PRIx "\n",
68
+ packet_desc_addr);
69
break;
70
}
71
72
--
73
2.5.0
74
75
diff view generated by jsdifflib
New patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
1
2
3
During wrap around and reset, queues are pointing to initial base
4
address of queue 0, irrespective of what queue we are dealing with.
5
Fix it by assigning proper base address every time.
6
7
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
11
hw/net/cadence_gem.c | 37 +++++++++++++++++++++++++++++++++----
12
1 file changed, 33 insertions(+), 4 deletions(-)
13
14
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/net/cadence_gem.c
17
+++ b/hw/net/cadence_gem.c
18
@@ -XXX,XX +XXX,XX @@ static int get_queue_from_screen(CadenceGEMState *s, uint8_t *rxbuf_ptr,
19
return 0;
20
}
21
22
+static uint32_t gem_get_queue_base_addr(CadenceGEMState *s, bool tx, int q)
23
+{
24
+ uint32_t base_addr = 0;
25
+
26
+ switch (q) {
27
+ case 0:
28
+ base_addr = s->regs[tx ? GEM_TXQBASE : GEM_RXQBASE];
29
+ break;
30
+ case 1 ... (MAX_PRIORITY_QUEUES - 1):
31
+ base_addr = s->regs[(tx ? GEM_TRANSMIT_Q1_PTR :
32
+ GEM_RECEIVE_Q1_PTR) + q - 1];
33
+ break;
34
+ default:
35
+ g_assert_not_reached();
36
+ };
37
+
38
+ return base_addr;
39
+}
40
+
41
+static inline uint32_t gem_get_tx_queue_base_addr(CadenceGEMState *s, int q)
42
+{
43
+ return gem_get_queue_base_addr(s, true, q);
44
+}
45
+
46
+static inline uint32_t gem_get_rx_queue_base_addr(CadenceGEMState *s, int q)
47
+{
48
+ return gem_get_queue_base_addr(s, false, q);
49
+}
50
+
51
static hwaddr gem_get_desc_addr(CadenceGEMState *s, bool tx, int q)
52
{
53
hwaddr desc_addr = 0;
54
@@ -XXX,XX +XXX,XX @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
55
/* Next descriptor */
56
if (rx_desc_get_wrap(s->rx_desc[q])) {
57
DB_PRINT("wrapping RX descriptor list\n");
58
- s->rx_desc_addr[q] = s->regs[GEM_RXQBASE];
59
+ s->rx_desc_addr[q] = gem_get_rx_queue_base_addr(s, q);
60
} else {
61
DB_PRINT("incrementing RX descriptor list\n");
62
s->rx_desc_addr[q] += 4 * gem_get_desc_len(s, true);
63
@@ -XXX,XX +XXX,XX @@ static void gem_transmit(CadenceGEMState *s)
64
sizeof(desc_first));
65
/* Advance the hardware current descriptor past this packet */
66
if (tx_desc_get_wrap(desc)) {
67
- s->tx_desc_addr[q] = s->regs[GEM_TXQBASE];
68
+ s->tx_desc_addr[q] = gem_get_tx_queue_base_addr(s, q);
69
} else {
70
s->tx_desc_addr[q] = packet_desc_addr +
71
4 * gem_get_desc_len(s, false);
72
@@ -XXX,XX +XXX,XX @@ static void gem_transmit(CadenceGEMState *s)
73
} else {
74
packet_desc_addr = 0;
75
}
76
- packet_desc_addr |= s->regs[GEM_TXQBASE];
77
+ packet_desc_addr |= gem_get_tx_queue_base_addr(s, q);
78
} else {
79
packet_desc_addr += 4 * gem_get_desc_len(s, false);
80
}
81
@@ -XXX,XX +XXX,XX @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
82
if (!(val & GEM_NWCTRL_TXENA)) {
83
/* Reset to start of Q when transmit disabled. */
84
for (i = 0; i < s->num_priority_queues; i++) {
85
- s->tx_desc_addr[i] = s->regs[GEM_TXQBASE];
86
+ s->tx_desc_addr[i] = gem_get_tx_queue_base_addr(s, i);
87
}
88
}
89
if (gem_can_receive(qemu_get_queue(s->nic))) {
90
--
91
2.5.0
92
93
diff view generated by jsdifflib
New patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
1
2
3
Set irq's specific to a queue, present implementation is setting q1 irq
4
based on q0 status.
5
6
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
7
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
10
hw/net/cadence_gem.c | 25 +++----------------------
11
1 file changed, 3 insertions(+), 22 deletions(-)
12
13
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/net/cadence_gem.c
16
+++ b/hw/net/cadence_gem.c
17
@@ -XXX,XX +XXX,XX @@ static void gem_update_int_status(CadenceGEMState *s)
18
{
19
int i;
20
21
- if (!s->regs[GEM_ISR]) {
22
- /* ISR isn't set, clear all the interrupts */
23
- for (i = 0; i < s->num_priority_queues; ++i) {
24
- qemu_set_irq(s->irq[i], 0);
25
- }
26
- return;
27
- }
28
+ qemu_set_irq(s->irq[0], !!s->regs[GEM_ISR]);
29
30
- /* If we get here we know s->regs[GEM_ISR] is set, so we don't need to
31
- * check it again.
32
- */
33
- if (s->num_priority_queues == 1) {
34
- /* No priority queues, just trigger the interrupt */
35
- DB_PRINT("asserting int.\n");
36
- qemu_set_irq(s->irq[0], 1);
37
- return;
38
- }
39
-
40
- for (i = 0; i < s->num_priority_queues; ++i) {
41
- if (s->regs[GEM_INT_Q1_STATUS + i]) {
42
- DB_PRINT("asserting int. (q=%d)\n", i);
43
- qemu_set_irq(s->irq[i], 1);
44
- }
45
+ for (i = 1; i < s->num_priority_queues; ++i) {
46
+ qemu_set_irq(s->irq[i], !!s->regs[GEM_INT_Q1_STATUS + i - 1]);
47
}
48
}
49
50
--
51
2.5.0
52
53
diff view generated by jsdifflib
New patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
1
2
3
Q1 to Q7 ISR's are clear-on-read, IER/IDR registers
4
are write-only, mask reg are read-only.
5
6
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
7
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
10
hw/net/cadence_gem.c | 14 ++++++++++++++
11
1 file changed, 14 insertions(+)
12
13
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/net/cadence_gem.c
16
+++ b/hw/net/cadence_gem.c
17
@@ -XXX,XX +XXX,XX @@ static const uint8_t broadcast_addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
18
*/
19
static void gem_init_register_masks(CadenceGEMState *s)
20
{
21
+ unsigned int i;
22
/* Mask of register bits which are read only */
23
memset(&s->regs_ro[0], 0, sizeof(s->regs_ro));
24
s->regs_ro[GEM_NWCTRL] = 0xFFF80000;
25
@@ -XXX,XX +XXX,XX @@ static void gem_init_register_masks(CadenceGEMState *s)
26
s->regs_ro[GEM_ISR] = 0xFFFFFFFF;
27
s->regs_ro[GEM_IMR] = 0xFFFFFFFF;
28
s->regs_ro[GEM_MODID] = 0xFFFFFFFF;
29
+ for (i = 0; i < s->num_priority_queues; i++) {
30
+ s->regs_ro[GEM_INT_Q1_STATUS + i] = 0xFFFFFFFF;
31
+ s->regs_ro[GEM_INT_Q1_ENABLE + i] = 0xFFFFF319;
32
+ s->regs_ro[GEM_INT_Q1_DISABLE + i] = 0xFFFFF319;
33
+ s->regs_ro[GEM_INT_Q1_MASK + i] = 0xFFFFFFFF;
34
+ }
35
36
/* Mask of register bits which are clear on read */
37
memset(&s->regs_rtc[0], 0, sizeof(s->regs_rtc));
38
s->regs_rtc[GEM_ISR] = 0xFFFFFFFF;
39
+ for (i = 0; i < s->num_priority_queues; i++) {
40
+ s->regs_rtc[GEM_INT_Q1_STATUS + i] = 0x00000CE6;
41
+ }
42
43
/* Mask of register bits which are write 1 to clear */
44
memset(&s->regs_w1c[0], 0, sizeof(s->regs_w1c));
45
@@ -XXX,XX +XXX,XX @@ static void gem_init_register_masks(CadenceGEMState *s)
46
s->regs_wo[GEM_NWCTRL] = 0x00073E60;
47
s->regs_wo[GEM_IER] = 0x07FFFFFF;
48
s->regs_wo[GEM_IDR] = 0x07FFFFFF;
49
+ for (i = 0; i < s->num_priority_queues; i++) {
50
+ s->regs_wo[GEM_INT_Q1_ENABLE + i] = 0x00000CE6;
51
+ s->regs_wo[GEM_INT_Q1_DISABLE + i] = 0x00000CE6;
52
+ }
53
}
54
55
/*
56
--
57
2.5.0
58
59
diff view generated by jsdifflib
New patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
1
2
3
Set ISR according to queue in use, added interrupt support for
4
all queues.
5
6
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
7
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
10
hw/net/cadence_gem.c | 27 +++++++++++++++++----------
11
1 file changed, 17 insertions(+), 10 deletions(-)
12
13
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/net/cadence_gem.c
16
+++ b/hw/net/cadence_gem.c
17
@@ -XXX,XX +XXX,XX @@ static inline void rx_desc_set_sar(uint32_t *desc, int sar_idx)
18
/* The broadcast MAC address: 0xFFFFFFFFFFFF */
19
static const uint8_t broadcast_addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
20
21
+static void gem_set_isr(CadenceGEMState *s, int q, uint32_t flag)
22
+{
23
+ if (q == 0) {
24
+ s->regs[GEM_ISR] |= flag & ~(s->regs[GEM_IMR]);
25
+ } else {
26
+ s->regs[GEM_INT_Q1_STATUS + q - 1] |= flag &
27
+ ~(s->regs[GEM_INT_Q1_MASK + q - 1]);
28
+ }
29
+}
30
+
31
/*
32
* gem_init_register_masks:
33
* One time initialization.
34
@@ -XXX,XX +XXX,XX @@ static void gem_get_rx_desc(CadenceGEMState *s, int q)
35
if (rx_desc_get_ownership(s->rx_desc[q]) == 1) {
36
DB_PRINT("descriptor 0x%" HWADDR_PRIx " owned by sw.\n", desc_addr);
37
s->regs[GEM_RXSTATUS] |= GEM_RXSTATUS_NOBUF;
38
- s->regs[GEM_ISR] |= GEM_INT_RXUSED & ~(s->regs[GEM_IMR]);
39
+ gem_set_isr(s, q, GEM_INT_RXUSED);
40
/* Handle interrupt consequences */
41
gem_update_int_status(s);
42
}
43
@@ -XXX,XX +XXX,XX @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
44
gem_receive_updatestats(s, buf, size);
45
46
s->regs[GEM_RXSTATUS] |= GEM_RXSTATUS_FRMRCVD;
47
- s->regs[GEM_ISR] |= GEM_INT_RXCMPL & ~(s->regs[GEM_IMR]);
48
+ gem_set_isr(s, q, GEM_INT_RXCMPL);
49
50
/* Handle interrupt consequences */
51
gem_update_int_status(s);
52
@@ -XXX,XX +XXX,XX @@ static void gem_transmit(CadenceGEMState *s)
53
DB_PRINT("TX descriptor next: 0x%08x\n", s->tx_desc_addr[q]);
54
55
s->regs[GEM_TXSTATUS] |= GEM_TXSTATUS_TXCMPL;
56
- s->regs[GEM_ISR] |= GEM_INT_TXCMPL & ~(s->regs[GEM_IMR]);
57
-
58
- /* Update queue interrupt status */
59
- if (s->num_priority_queues > 1) {
60
- s->regs[GEM_INT_Q1_STATUS + q] |=
61
- GEM_INT_TXCMPL & ~(s->regs[GEM_INT_Q1_MASK + q]);
62
- }
63
+ gem_set_isr(s, q, GEM_INT_TXCMPL);
64
65
/* Handle interrupt consequences */
66
gem_update_int_status(s);
67
@@ -XXX,XX +XXX,XX @@ static void gem_transmit(CadenceGEMState *s)
68
69
if (tx_desc_get_used(desc)) {
70
s->regs[GEM_TXSTATUS] |= GEM_TXSTATUS_USED;
71
- s->regs[GEM_ISR] |= GEM_INT_TXUSED & ~(s->regs[GEM_IMR]);
72
+ /* IRQ TXUSED is defined only for queue 0 */
73
+ if (q == 0) {
74
+ gem_set_isr(s, 0, GEM_INT_TXUSED);
75
+ }
76
gem_update_int_status(s);
77
}
78
}
79
--
80
2.5.0
81
82
diff view generated by jsdifflib
New patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
1
2
3
Moving this buffers to CadenceGEMState, as their size will be increased
4
more when JUMBO frames support is added.
5
6
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
7
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
10
hw/net/cadence_gem.c | 38 +++++++++++++++++---------------------
11
include/hw/net/cadence_gem.h | 4 ++++
12
2 files changed, 21 insertions(+), 21 deletions(-)
13
14
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/net/cadence_gem.c
17
+++ b/hw/net/cadence_gem.c
18
@@ -XXX,XX +XXX,XX @@ static void gem_get_rx_desc(CadenceGEMState *s, int q)
19
*/
20
static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
21
{
22
- CadenceGEMState *s;
23
+ CadenceGEMState *s = qemu_get_nic_opaque(nc);
24
unsigned rxbufsize, bytes_to_copy;
25
unsigned rxbuf_offset;
26
- uint8_t rxbuf[2048];
27
uint8_t *rxbuf_ptr;
28
bool first_desc = true;
29
int maf;
30
int q = 0;
31
32
- s = qemu_get_nic_opaque(nc);
33
-
34
/* Is this destination MAC address "for us" ? */
35
maf = gem_mac_address_filter(s, buf);
36
if (maf == GEM_RX_REJECT) {
37
@@ -XXX,XX +XXX,XX @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
38
} else {
39
unsigned crc_val;
40
41
- if (size > sizeof(rxbuf) - sizeof(crc_val)) {
42
- size = sizeof(rxbuf) - sizeof(crc_val);
43
+ if (size > MAX_FRAME_SIZE - sizeof(crc_val)) {
44
+ size = MAX_FRAME_SIZE - sizeof(crc_val);
45
}
46
bytes_to_copy = size;
47
/* The application wants the FCS field, which QEMU does not provide.
48
* We must try and calculate one.
49
*/
50
51
- memcpy(rxbuf, buf, size);
52
- memset(rxbuf + size, 0, sizeof(rxbuf) - size);
53
- rxbuf_ptr = rxbuf;
54
- crc_val = cpu_to_le32(crc32(0, rxbuf, MAX(size, 60)));
55
- memcpy(rxbuf + size, &crc_val, sizeof(crc_val));
56
+ memcpy(s->rx_packet, buf, size);
57
+ memset(s->rx_packet + size, 0, MAX_FRAME_SIZE - size);
58
+ rxbuf_ptr = s->rx_packet;
59
+ crc_val = cpu_to_le32(crc32(0, s->rx_packet, MAX(size, 60)));
60
+ memcpy(s->rx_packet + size, &crc_val, sizeof(crc_val));
61
62
bytes_to_copy += 4;
63
size += 4;
64
@@ -XXX,XX +XXX,XX @@ static void gem_transmit(CadenceGEMState *s)
65
{
66
uint32_t desc[DESC_MAX_NUM_WORDS];
67
hwaddr packet_desc_addr;
68
- uint8_t tx_packet[2048];
69
uint8_t *p;
70
unsigned total_bytes;
71
int q = 0;
72
@@ -XXX,XX +XXX,XX @@ static void gem_transmit(CadenceGEMState *s)
73
* Packets scattered across multiple descriptors are gathered to this
74
* one contiguous buffer first.
75
*/
76
- p = tx_packet;
77
+ p = s->tx_packet;
78
total_bytes = 0;
79
80
for (q = s->num_priority_queues - 1; q >= 0; q--) {
81
@@ -XXX,XX +XXX,XX @@ static void gem_transmit(CadenceGEMState *s)
82
break;
83
}
84
85
- if (tx_desc_get_length(desc) > sizeof(tx_packet) -
86
- (p - tx_packet)) {
87
+ if (tx_desc_get_length(desc) > MAX_FRAME_SIZE -
88
+ (p - s->tx_packet)) {
89
DB_PRINT("TX descriptor @ 0x%" HWADDR_PRIx \
90
" too large: size 0x%x space 0x%zx\n",
91
packet_desc_addr, tx_desc_get_length(desc),
92
- sizeof(tx_packet) - (p - tx_packet));
93
+ MAX_FRAME_SIZE - (p - s->tx_packet));
94
break;
95
}
96
97
@@ -XXX,XX +XXX,XX @@ static void gem_transmit(CadenceGEMState *s)
98
99
/* Is checksum offload enabled? */
100
if (s->regs[GEM_DMACFG] & GEM_DMACFG_TXCSUM_OFFL) {
101
- net_checksum_calculate(tx_packet, total_bytes);
102
+ net_checksum_calculate(s->tx_packet, total_bytes);
103
}
104
105
/* Update MAC statistics */
106
- gem_transmit_updatestats(s, tx_packet, total_bytes);
107
+ gem_transmit_updatestats(s, s->tx_packet, total_bytes);
108
109
/* Send the packet somewhere */
110
if (s->phy_loop || (s->regs[GEM_NWCTRL] &
111
GEM_NWCTRL_LOCALLOOP)) {
112
- gem_receive(qemu_get_queue(s->nic), tx_packet,
113
+ gem_receive(qemu_get_queue(s->nic), s->tx_packet,
114
total_bytes);
115
} else {
116
- qemu_send_packet(qemu_get_queue(s->nic), tx_packet,
117
+ qemu_send_packet(qemu_get_queue(s->nic), s->tx_packet,
118
total_bytes);
119
}
120
121
/* Prepare for next packet */
122
- p = tx_packet;
123
+ p = s->tx_packet;
124
total_bytes = 0;
125
}
126
127
diff --git a/include/hw/net/cadence_gem.h b/include/hw/net/cadence_gem.h
128
index XXXXXXX..XXXXXXX 100644
129
--- a/include/hw/net/cadence_gem.h
130
+++ b/include/hw/net/cadence_gem.h
131
@@ -XXX,XX +XXX,XX @@
132
#define MAX_TYPE1_SCREENERS 16
133
#define MAX_TYPE2_SCREENERS 16
134
135
+#define MAX_FRAME_SIZE 2048
136
+
137
typedef struct CadenceGEMState {
138
/*< private >*/
139
SysBusDevice parent_obj;
140
@@ -XXX,XX +XXX,XX @@ typedef struct CadenceGEMState {
141
142
uint8_t can_rx_state; /* Debug only */
143
144
+ uint8_t tx_packet[MAX_FRAME_SIZE];
145
+ uint8_t rx_packet[MAX_FRAME_SIZE];
146
uint32_t rx_desc[MAX_PRIORITY_QUEUES][DESC_MAX_NUM_WORDS];
147
148
bool sar_active[4];
149
--
150
2.5.0
151
152
diff view generated by jsdifflib
New patch
1
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
2
3
Fix the code style for register definitions.
4
5
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
9
hw/net/cadence_gem.c | 204 ++++++++++++++++++++++++++-------------------------
10
1 file changed, 103 insertions(+), 101 deletions(-)
11
12
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/net/cadence_gem.c
15
+++ b/hw/net/cadence_gem.c
16
@@ -XXX,XX +XXX,XX @@
17
} \
18
} while (0)
19
20
-#define GEM_NWCTRL (0x00000000/4) /* Network Control reg */
21
-#define GEM_NWCFG (0x00000004/4) /* Network Config reg */
22
-#define GEM_NWSTATUS (0x00000008/4) /* Network Status reg */
23
-#define GEM_USERIO (0x0000000C/4) /* User IO reg */
24
-#define GEM_DMACFG (0x00000010/4) /* DMA Control reg */
25
-#define GEM_TXSTATUS (0x00000014/4) /* TX Status reg */
26
-#define GEM_RXQBASE (0x00000018/4) /* RX Q Base address reg */
27
-#define GEM_TXQBASE (0x0000001C/4) /* TX Q Base address reg */
28
-#define GEM_RXSTATUS (0x00000020/4) /* RX Status reg */
29
-#define GEM_ISR (0x00000024/4) /* Interrupt Status reg */
30
-#define GEM_IER (0x00000028/4) /* Interrupt Enable reg */
31
-#define GEM_IDR (0x0000002C/4) /* Interrupt Disable reg */
32
-#define GEM_IMR (0x00000030/4) /* Interrupt Mask reg */
33
-#define GEM_PHYMNTNC (0x00000034/4) /* Phy Maintenance reg */
34
-#define GEM_RXPAUSE (0x00000038/4) /* RX Pause Time reg */
35
-#define GEM_TXPAUSE (0x0000003C/4) /* TX Pause Time reg */
36
-#define GEM_TXPARTIALSF (0x00000040/4) /* TX Partial Store and Forward */
37
-#define GEM_RXPARTIALSF (0x00000044/4) /* RX Partial Store and Forward */
38
-#define GEM_HASHLO (0x00000080/4) /* Hash Low address reg */
39
-#define GEM_HASHHI (0x00000084/4) /* Hash High address reg */
40
-#define GEM_SPADDR1LO (0x00000088/4) /* Specific addr 1 low reg */
41
-#define GEM_SPADDR1HI (0x0000008C/4) /* Specific addr 1 high reg */
42
-#define GEM_SPADDR2LO (0x00000090/4) /* Specific addr 2 low reg */
43
-#define GEM_SPADDR2HI (0x00000094/4) /* Specific addr 2 high reg */
44
-#define GEM_SPADDR3LO (0x00000098/4) /* Specific addr 3 low reg */
45
-#define GEM_SPADDR3HI (0x0000009C/4) /* Specific addr 3 high reg */
46
-#define GEM_SPADDR4LO (0x000000A0/4) /* Specific addr 4 low reg */
47
-#define GEM_SPADDR4HI (0x000000A4/4) /* Specific addr 4 high reg */
48
-#define GEM_TIDMATCH1 (0x000000A8/4) /* Type ID1 Match reg */
49
-#define GEM_TIDMATCH2 (0x000000AC/4) /* Type ID2 Match reg */
50
-#define GEM_TIDMATCH3 (0x000000B0/4) /* Type ID3 Match reg */
51
-#define GEM_TIDMATCH4 (0x000000B4/4) /* Type ID4 Match reg */
52
-#define GEM_WOLAN (0x000000B8/4) /* Wake on LAN reg */
53
-#define GEM_IPGSTRETCH (0x000000BC/4) /* IPG Stretch reg */
54
-#define GEM_SVLAN (0x000000C0/4) /* Stacked VLAN reg */
55
-#define GEM_MODID (0x000000FC/4) /* Module ID reg */
56
-#define GEM_OCTTXLO (0x00000100/4) /* Octects transmitted Low reg */
57
-#define GEM_OCTTXHI (0x00000104/4) /* Octects transmitted High reg */
58
-#define GEM_TXCNT (0x00000108/4) /* Error-free Frames transmitted */
59
-#define GEM_TXBCNT (0x0000010C/4) /* Error-free Broadcast Frames */
60
-#define GEM_TXMCNT (0x00000110/4) /* Error-free Multicast Frame */
61
-#define GEM_TXPAUSECNT (0x00000114/4) /* Pause Frames Transmitted */
62
-#define GEM_TX64CNT (0x00000118/4) /* Error-free 64 TX */
63
-#define GEM_TX65CNT (0x0000011C/4) /* Error-free 65-127 TX */
64
-#define GEM_TX128CNT (0x00000120/4) /* Error-free 128-255 TX */
65
-#define GEM_TX256CNT (0x00000124/4) /* Error-free 256-511 */
66
-#define GEM_TX512CNT (0x00000128/4) /* Error-free 512-1023 TX */
67
-#define GEM_TX1024CNT (0x0000012C/4) /* Error-free 1024-1518 TX */
68
-#define GEM_TX1519CNT (0x00000130/4) /* Error-free larger than 1519 TX */
69
-#define GEM_TXURUNCNT (0x00000134/4) /* TX under run error counter */
70
-#define GEM_SINGLECOLLCNT (0x00000138/4) /* Single Collision Frames */
71
-#define GEM_MULTCOLLCNT (0x0000013C/4) /* Multiple Collision Frames */
72
-#define GEM_EXCESSCOLLCNT (0x00000140/4) /* Excessive Collision Frames */
73
-#define GEM_LATECOLLCNT (0x00000144/4) /* Late Collision Frames */
74
-#define GEM_DEFERTXCNT (0x00000148/4) /* Deferred Transmission Frames */
75
-#define GEM_CSENSECNT (0x0000014C/4) /* Carrier Sense Error Counter */
76
-#define GEM_OCTRXLO (0x00000150/4) /* Octects Received register Low */
77
-#define GEM_OCTRXHI (0x00000154/4) /* Octects Received register High */
78
-#define GEM_RXCNT (0x00000158/4) /* Error-free Frames Received */
79
-#define GEM_RXBROADCNT (0x0000015C/4) /* Error-free Broadcast Frames RX */
80
-#define GEM_RXMULTICNT (0x00000160/4) /* Error-free Multicast Frames RX */
81
-#define GEM_RXPAUSECNT (0x00000164/4) /* Pause Frames Received Counter */
82
-#define GEM_RX64CNT (0x00000168/4) /* Error-free 64 byte Frames RX */
83
-#define GEM_RX65CNT (0x0000016C/4) /* Error-free 65-127B Frames RX */
84
-#define GEM_RX128CNT (0x00000170/4) /* Error-free 128-255B Frames RX */
85
-#define GEM_RX256CNT (0x00000174/4) /* Error-free 256-512B Frames RX */
86
-#define GEM_RX512CNT (0x00000178/4) /* Error-free 512-1023B Frames RX */
87
-#define GEM_RX1024CNT (0x0000017C/4) /* Error-free 1024-1518B Frames RX */
88
-#define GEM_RX1519CNT (0x00000180/4) /* Error-free 1519-max Frames RX */
89
-#define GEM_RXUNDERCNT (0x00000184/4) /* Undersize Frames Received */
90
-#define GEM_RXOVERCNT (0x00000188/4) /* Oversize Frames Received */
91
-#define GEM_RXJABCNT (0x0000018C/4) /* Jabbers Received Counter */
92
-#define GEM_RXFCSCNT (0x00000190/4) /* Frame Check seq. Error Counter */
93
-#define GEM_RXLENERRCNT (0x00000194/4) /* Length Field Error Counter */
94
-#define GEM_RXSYMERRCNT (0x00000198/4) /* Symbol Error Counter */
95
-#define GEM_RXALIGNERRCNT (0x0000019C/4) /* Alignment Error Counter */
96
-#define GEM_RXRSCERRCNT (0x000001A0/4) /* Receive Resource Error Counter */
97
-#define GEM_RXORUNCNT (0x000001A4/4) /* Receive Overrun Counter */
98
-#define GEM_RXIPCSERRCNT (0x000001A8/4) /* IP header Checksum Error Counter */
99
-#define GEM_RXTCPCCNT (0x000001AC/4) /* TCP Checksum Error Counter */
100
-#define GEM_RXUDPCCNT (0x000001B0/4) /* UDP Checksum Error Counter */
101
-
102
-#define GEM_1588S (0x000001D0/4) /* 1588 Timer Seconds */
103
-#define GEM_1588NS (0x000001D4/4) /* 1588 Timer Nanoseconds */
104
-#define GEM_1588ADJ (0x000001D8/4) /* 1588 Timer Adjust */
105
-#define GEM_1588INC (0x000001DC/4) /* 1588 Timer Increment */
106
-#define GEM_PTPETXS (0x000001E0/4) /* PTP Event Frame Transmitted (s) */
107
-#define GEM_PTPETXNS (0x000001E4/4) /* PTP Event Frame Transmitted (ns) */
108
-#define GEM_PTPERXS (0x000001E8/4) /* PTP Event Frame Received (s) */
109
-#define GEM_PTPERXNS (0x000001EC/4) /* PTP Event Frame Received (ns) */
110
-#define GEM_PTPPTXS (0x000001E0/4) /* PTP Peer Frame Transmitted (s) */
111
-#define GEM_PTPPTXNS (0x000001E4/4) /* PTP Peer Frame Transmitted (ns) */
112
-#define GEM_PTPPRXS (0x000001E8/4) /* PTP Peer Frame Received (s) */
113
-#define GEM_PTPPRXNS (0x000001EC/4) /* PTP Peer Frame Received (ns) */
114
+#define GEM_NWCTRL (0x00000000 / 4) /* Network Control reg */
115
+#define GEM_NWCFG (0x00000004 / 4) /* Network Config reg */
116
+#define GEM_NWSTATUS (0x00000008 / 4) /* Network Status reg */
117
+#define GEM_USERIO (0x0000000C / 4) /* User IO reg */
118
+#define GEM_DMACFG (0x00000010 / 4) /* DMA Control reg */
119
+#define GEM_TXSTATUS (0x00000014 / 4) /* TX Status reg */
120
+#define GEM_RXQBASE (0x00000018 / 4) /* RX Q Base address reg */
121
+#define GEM_TXQBASE (0x0000001C / 4) /* TX Q Base address reg */
122
+#define GEM_RXSTATUS (0x00000020 / 4) /* RX Status reg */
123
+#define GEM_ISR (0x00000024 / 4) /* Interrupt Status reg */
124
+#define GEM_IER (0x00000028 / 4) /* Interrupt Enable reg */
125
+#define GEM_IDR (0x0000002C / 4) /* Interrupt Disable reg */
126
+#define GEM_IMR (0x00000030 / 4) /* Interrupt Mask reg */
127
+#define GEM_PHYMNTNC (0x00000034 / 4) /* Phy Maintenance reg */
128
+#define GEM_RXPAUSE (0x00000038 / 4) /* RX Pause Time reg */
129
+#define GEM_TXPAUSE (0x0000003C / 4) /* TX Pause Time reg */
130
+#define GEM_TXPARTIALSF (0x00000040 / 4) /* TX Partial Store and Forward */
131
+#define GEM_RXPARTIALSF (0x00000044 / 4) /* RX Partial Store and Forward */
132
+#define GEM_HASHLO (0x00000080 / 4) /* Hash Low address reg */
133
+#define GEM_HASHHI (0x00000084 / 4) /* Hash High address reg */
134
+#define GEM_SPADDR1LO (0x00000088 / 4) /* Specific addr 1 low reg */
135
+#define GEM_SPADDR1HI (0x0000008C / 4) /* Specific addr 1 high reg */
136
+#define GEM_SPADDR2LO (0x00000090 / 4) /* Specific addr 2 low reg */
137
+#define GEM_SPADDR2HI (0x00000094 / 4) /* Specific addr 2 high reg */
138
+#define GEM_SPADDR3LO (0x00000098 / 4) /* Specific addr 3 low reg */
139
+#define GEM_SPADDR3HI (0x0000009C / 4) /* Specific addr 3 high reg */
140
+#define GEM_SPADDR4LO (0x000000A0 / 4) /* Specific addr 4 low reg */
141
+#define GEM_SPADDR4HI (0x000000A4 / 4) /* Specific addr 4 high reg */
142
+#define GEM_TIDMATCH1 (0x000000A8 / 4) /* Type ID1 Match reg */
143
+#define GEM_TIDMATCH2 (0x000000AC / 4) /* Type ID2 Match reg */
144
+#define GEM_TIDMATCH3 (0x000000B0 / 4) /* Type ID3 Match reg */
145
+#define GEM_TIDMATCH4 (0x000000B4 / 4) /* Type ID4 Match reg */
146
+#define GEM_WOLAN (0x000000B8 / 4) /* Wake on LAN reg */
147
+#define GEM_IPGSTRETCH (0x000000BC / 4) /* IPG Stretch reg */
148
+#define GEM_SVLAN (0x000000C0 / 4) /* Stacked VLAN reg */
149
+#define GEM_MODID (0x000000FC / 4) /* Module ID reg */
150
+#define GEM_OCTTXLO (0x00000100 / 4) /* Octects transmitted Low reg */
151
+#define GEM_OCTTXHI (0x00000104 / 4) /* Octects transmitted High reg */
152
+#define GEM_TXCNT (0x00000108 / 4) /* Error-free Frames transmitted */
153
+#define GEM_TXBCNT (0x0000010C / 4) /* Error-free Broadcast Frames */
154
+#define GEM_TXMCNT (0x00000110 / 4) /* Error-free Multicast Frame */
155
+#define GEM_TXPAUSECNT (0x00000114 / 4) /* Pause Frames Transmitted */
156
+#define GEM_TX64CNT (0x00000118 / 4) /* Error-free 64 TX */
157
+#define GEM_TX65CNT (0x0000011C / 4) /* Error-free 65-127 TX */
158
+#define GEM_TX128CNT (0x00000120 / 4) /* Error-free 128-255 TX */
159
+#define GEM_TX256CNT (0x00000124 / 4) /* Error-free 256-511 */
160
+#define GEM_TX512CNT (0x00000128 / 4) /* Error-free 512-1023 TX */
161
+#define GEM_TX1024CNT (0x0000012C / 4) /* Error-free 1024-1518 TX */
162
+#define GEM_TX1519CNT (0x00000130 / 4) /* Error-free larger than 1519 TX */
163
+#define GEM_TXURUNCNT (0x00000134 / 4) /* TX under run error counter */
164
+#define GEM_SINGLECOLLCNT (0x00000138 / 4) /* Single Collision Frames */
165
+#define GEM_MULTCOLLCNT (0x0000013C / 4) /* Multiple Collision Frames */
166
+#define GEM_EXCESSCOLLCNT (0x00000140 / 4) /* Excessive Collision Frames */
167
+#define GEM_LATECOLLCNT (0x00000144 / 4) /* Late Collision Frames */
168
+#define GEM_DEFERTXCNT (0x00000148 / 4) /* Deferred Transmission Frames */
169
+#define GEM_CSENSECNT (0x0000014C / 4) /* Carrier Sense Error Counter */
170
+#define GEM_OCTRXLO (0x00000150 / 4) /* Octects Received register Low */
171
+#define GEM_OCTRXHI (0x00000154 / 4) /* Octects Received register High */
172
+#define GEM_RXCNT (0x00000158 / 4) /* Error-free Frames Received */
173
+#define GEM_RXBROADCNT (0x0000015C / 4) /* Error-free Broadcast Frames RX */
174
+#define GEM_RXMULTICNT (0x00000160 / 4) /* Error-free Multicast Frames RX */
175
+#define GEM_RXPAUSECNT (0x00000164 / 4) /* Pause Frames Received Counter */
176
+#define GEM_RX64CNT (0x00000168 / 4) /* Error-free 64 byte Frames RX */
177
+#define GEM_RX65CNT (0x0000016C / 4) /* Error-free 65-127B Frames RX */
178
+#define GEM_RX128CNT (0x00000170 / 4) /* Error-free 128-255B Frames RX */
179
+#define GEM_RX256CNT (0x00000174 / 4) /* Error-free 256-512B Frames RX */
180
+#define GEM_RX512CNT (0x00000178 / 4) /* Error-free 512-1023B Frames RX */
181
+#define GEM_RX1024CNT (0x0000017C / 4) /* Error-free 1024-1518B Frames RX */
182
+#define GEM_RX1519CNT (0x00000180 / 4) /* Error-free 1519-max Frames RX */
183
+#define GEM_RXUNDERCNT (0x00000184 / 4) /* Undersize Frames Received */
184
+#define GEM_RXOVERCNT (0x00000188 / 4) /* Oversize Frames Received */
185
+#define GEM_RXJABCNT (0x0000018C / 4) /* Jabbers Received Counter */
186
+#define GEM_RXFCSCNT (0x00000190 / 4) /* Frame Check seq. Error Counter */
187
+#define GEM_RXLENERRCNT (0x00000194 / 4) /* Length Field Error Counter */
188
+#define GEM_RXSYMERRCNT (0x00000198 / 4) /* Symbol Error Counter */
189
+#define GEM_RXALIGNERRCNT (0x0000019C / 4) /* Alignment Error Counter */
190
+#define GEM_RXRSCERRCNT (0x000001A0 / 4) /* Receive Resource Error Counter */
191
+#define GEM_RXORUNCNT (0x000001A4 / 4) /* Receive Overrun Counter */
192
+#define GEM_RXIPCSERRCNT (0x000001A8 / 4) /* IP header Checksum Err Counter */
193
+#define GEM_RXTCPCCNT (0x000001AC / 4) /* TCP Checksum Error Counter */
194
+#define GEM_RXUDPCCNT (0x000001B0 / 4) /* UDP Checksum Error Counter */
195
+
196
+#define GEM_1588S (0x000001D0 / 4) /* 1588 Timer Seconds */
197
+#define GEM_1588NS (0x000001D4 / 4) /* 1588 Timer Nanoseconds */
198
+#define GEM_1588ADJ (0x000001D8 / 4) /* 1588 Timer Adjust */
199
+#define GEM_1588INC (0x000001DC / 4) /* 1588 Timer Increment */
200
+#define GEM_PTPETXS (0x000001E0 / 4) /* PTP Event Frame Transmitted (s) */
201
+#define GEM_PTPETXNS (0x000001E4 / 4) /*
202
+ * PTP Event Frame Transmitted (ns)
203
+ */
204
+#define GEM_PTPERXS (0x000001E8 / 4) /* PTP Event Frame Received (s) */
205
+#define GEM_PTPERXNS (0x000001EC / 4) /* PTP Event Frame Received (ns) */
206
+#define GEM_PTPPTXS (0x000001E0 / 4) /* PTP Peer Frame Transmitted (s) */
207
+#define GEM_PTPPTXNS (0x000001E4 / 4) /* PTP Peer Frame Transmitted (ns) */
208
+#define GEM_PTPPRXS (0x000001E8 / 4) /* PTP Peer Frame Received (s) */
209
+#define GEM_PTPPRXNS (0x000001EC / 4) /* PTP Peer Frame Received (ns) */
210
211
/* Design Configuration Registers */
212
-#define GEM_DESCONF (0x00000280/4)
213
-#define GEM_DESCONF2 (0x00000284/4)
214
-#define GEM_DESCONF3 (0x00000288/4)
215
-#define GEM_DESCONF4 (0x0000028C/4)
216
-#define GEM_DESCONF5 (0x00000290/4)
217
-#define GEM_DESCONF6 (0x00000294/4)
218
+#define GEM_DESCONF (0x00000280 / 4)
219
+#define GEM_DESCONF2 (0x00000284 / 4)
220
+#define GEM_DESCONF3 (0x00000288 / 4)
221
+#define GEM_DESCONF4 (0x0000028C / 4)
222
+#define GEM_DESCONF5 (0x00000290 / 4)
223
+#define GEM_DESCONF6 (0x00000294 / 4)
224
#define GEM_DESCONF6_64B_MASK (1U << 23)
225
-#define GEM_DESCONF7 (0x00000298/4)
226
+#define GEM_DESCONF7 (0x00000298 / 4)
227
228
#define GEM_INT_Q1_STATUS (0x00000400 / 4)
229
#define GEM_INT_Q1_MASK (0x00000640 / 4)
230
--
231
2.5.0
232
233
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
2
2
3
We add the vnet_hdr_support option for filter-rewriter, default is disabled.
3
Add a property "jumbo-max-len", which sets default value of jumbo frames
4
If you use virtio-net-pci or other driver needs vnet_hdr, please enable it.
4
up to 16,383 bytes. Add Frame length checks for standard and jumbo
5
You can use it for example:
5
frames.
6
-object filter-rewriter,id=rew0,netdev=hn0,queue=all,vnet_hdr_support
7
6
8
We get the vnet_hdr_len from NetClientState that make us
7
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
9
parse net packet correctly.
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
10
11
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
---
10
---
14
net/filter-rewriter.c | 37 ++++++++++++++++++++++++++++++++++++-
11
hw/net/cadence_gem.c | 51 +++++++++++++++++++++++++++++++++++++++-----
15
qemu-options.hx | 4 ++--
12
include/hw/net/cadence_gem.h | 4 +++-
16
2 files changed, 38 insertions(+), 3 deletions(-)
13
2 files changed, 49 insertions(+), 6 deletions(-)
17
14
18
diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c
15
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
19
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
20
--- a/net/filter-rewriter.c
17
--- a/hw/net/cadence_gem.c
21
+++ b/net/filter-rewriter.c
18
+++ b/hw/net/cadence_gem.c
22
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
23
#include "qemu-common.h"
20
#define GEM_TXPAUSE (0x0000003C / 4) /* TX Pause Time reg */
24
#include "qapi/error.h"
21
#define GEM_TXPARTIALSF (0x00000040 / 4) /* TX Partial Store and Forward */
25
#include "qapi/qmp/qerror.h"
22
#define GEM_RXPARTIALSF (0x00000044 / 4) /* RX Partial Store and Forward */
26
+#include "qemu/error-report.h"
23
+#define GEM_JUMBO_MAX_LEN (0x00000048 / 4) /* Max Jumbo Frame Size */
27
#include "qapi-visit.h"
24
#define GEM_HASHLO (0x00000080 / 4) /* Hash Low address reg */
28
#include "qom/object.h"
25
#define GEM_HASHHI (0x00000084 / 4) /* Hash High address reg */
29
#include "qemu/main-loop.h"
26
#define GEM_SPADDR1LO (0x00000088 / 4) /* Specific addr 1 low reg */
30
@@ -XXX,XX +XXX,XX @@ typedef struct RewriterState {
27
@@ -XXX,XX +XXX,XX @@
31
NetQueue *incoming_queue;
28
#define GEM_NWCFG_LERR_DISC 0x00010000 /* Discard RX frames with len err */
32
/* hashtable to save connection */
29
#define GEM_NWCFG_BUFF_OFST_M 0x0000C000 /* Receive buffer offset mask */
33
GHashTable *connection_track_table;
30
#define GEM_NWCFG_BUFF_OFST_S 14 /* Receive buffer offset shift */
34
+ bool vnet_hdr;
31
+#define GEM_NWCFG_RCV_1538 0x00000100 /* Receive 1538 bytes frame */
35
} RewriterState;
32
#define GEM_NWCFG_UCAST_HASH 0x00000080 /* accept unicast if hash match */
36
33
#define GEM_NWCFG_MCAST_HASH 0x00000040 /* accept multicast if hash match */
37
static void filter_rewriter_flush(NetFilterState *nf)
34
#define GEM_NWCFG_BCAST_REJ 0x00000020 /* Reject broadcast packets */
38
@@ -XXX,XX +XXX,XX @@ static ssize_t colo_rewriter_receive_iov(NetFilterState *nf,
35
#define GEM_NWCFG_PROMISC 0x00000010 /* Accept all packets */
39
ConnectionKey key;
36
+#define GEM_NWCFG_JUMBO_FRAME 0x00000008 /* Jumbo Frames enable */
40
Packet *pkt;
37
41
ssize_t size = iov_size(iov, iovcnt);
38
#define GEM_DMACFG_ADDR_64B (1U << 30)
42
+ ssize_t vnet_hdr_len = 0;
39
#define GEM_DMACFG_TX_BD_EXT (1U << 29)
43
char *buf = g_malloc0(size);
40
@@ -XXX,XX +XXX,XX @@
44
41
45
iov_to_buf(iov, iovcnt, 0, buf, size);
42
/* GEM_ISR GEM_IER GEM_IDR GEM_IMR */
46
- pkt = packet_new(buf, size, 0);
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
+}
47
+
69
+
48
+ if (s->vnet_hdr) {
70
static void gem_set_isr(CadenceGEMState *s, int q, uint32_t flag)
49
+ vnet_hdr_len = nf->netdev->vnet_hdr_len;
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;
50
+ }
81
+ }
51
+
82
+
52
+ pkt = packet_new(buf, size, vnet_hdr_len);
83
while (bytes_to_copy) {
53
g_free(buf);
84
hwaddr desc_addr;
54
85
55
/*
86
@@ -XXX,XX +XXX,XX @@ static void gem_transmit(CadenceGEMState *s)
56
@@ -XXX,XX +XXX,XX @@ static void colo_rewriter_setup(NetFilterState *nf, Error **errp)
87
break;
57
s->incoming_queue = qemu_new_net_queue(qemu_netfilter_pass_to_next, nf);
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
+ }
58
}
136
}
59
137
60
+static bool filter_rewriter_get_vnet_hdr(Object *obj, Error **errp)
138
static void gem_init(Object *obj)
61
+{
139
@@ -XXX,XX +XXX,XX @@ static Property gem_properties[] = {
62
+ RewriterState *s = FILTER_COLO_REWRITER(obj);
140
num_type1_screeners, 4),
63
+
141
DEFINE_PROP_UINT8("num-type2-screeners", CadenceGEMState,
64
+ return s->vnet_hdr;
142
num_type2_screeners, 4),
65
+}
143
+ DEFINE_PROP_UINT16("jumbo-max-len", CadenceGEMState,
66
+
144
+ jumbo_max_len, 10240),
67
+static void filter_rewriter_set_vnet_hdr(Object *obj,
145
DEFINE_PROP_END_OF_LIST(),
68
+ bool value,
69
+ Error **errp)
70
+{
71
+ RewriterState *s = FILTER_COLO_REWRITER(obj);
72
+
73
+ s->vnet_hdr = value;
74
+}
75
+
76
+static void filter_rewriter_init(Object *obj)
77
+{
78
+ RewriterState *s = FILTER_COLO_REWRITER(obj);
79
+
80
+ s->vnet_hdr = false;
81
+ object_property_add_bool(obj, "vnet_hdr_support",
82
+ filter_rewriter_get_vnet_hdr,
83
+ filter_rewriter_set_vnet_hdr, NULL);
84
+}
85
+
86
static void colo_rewriter_class_init(ObjectClass *oc, void *data)
87
{
88
NetFilterClass *nfc = NETFILTER_CLASS(oc);
89
@@ -XXX,XX +XXX,XX @@ static const TypeInfo colo_rewriter_info = {
90
.name = TYPE_FILTER_REWRITER,
91
.parent = TYPE_NETFILTER,
92
.class_init = colo_rewriter_class_init,
93
+ .instance_init = filter_rewriter_init,
94
.instance_size = sizeof(RewriterState),
95
};
146
};
96
147
97
diff --git a/qemu-options.hx b/qemu-options.hx
148
diff --git a/include/hw/net/cadence_gem.h b/include/hw/net/cadence_gem.h
98
index XXXXXXX..XXXXXXX 100644
149
index XXXXXXX..XXXXXXX 100644
99
--- a/qemu-options.hx
150
--- a/include/hw/net/cadence_gem.h
100
+++ b/qemu-options.hx
151
+++ b/include/hw/net/cadence_gem.h
101
@@ -XXX,XX +XXX,XX @@ Create a filter-redirector we need to differ outdev id from indev id, id can not
152
@@ -XXX,XX +XXX,XX @@
102
be the same. we can just use indev or outdev, but at least one of indev or outdev
153
#define MAX_TYPE1_SCREENERS 16
103
need to be specified.
154
#define MAX_TYPE2_SCREENERS 16
104
155
105
-@item -object filter-rewriter,id=@var{id},netdev=@var{netdevid}[,queue=@var{all|rx|tx}]
156
-#define MAX_FRAME_SIZE 2048
106
+@item -object filter-rewriter,id=@var{id},netdev=@var{netdevid},queue=@var{all|rx|tx},[vnet_hdr_support]
157
+#define MAX_JUMBO_FRAME_SIZE_MASK 0x3FFF
107
158
+#define MAX_FRAME_SIZE MAX_JUMBO_FRAME_SIZE_MASK
108
Filter-rewriter is a part of COLO project.It will rewrite tcp packet to
159
109
secondary from primary to keep secondary tcp connection,and rewrite
160
typedef struct CadenceGEMState {
110
tcp packet to primary from secondary make tcp packet can be handled by
161
/*< private >*/
111
-client.
162
@@ -XXX,XX +XXX,XX @@ typedef struct CadenceGEMState {
112
+client.if it has the vnet_hdr_support flag, we can parse packet with vnet header.
163
uint8_t num_type1_screeners;
113
164
uint8_t num_type2_screeners;
114
usage:
165
uint32_t revision;
115
colo secondary:
166
+ uint16_t jumbo_max_len;
167
168
/* GEM registers backing store */
169
uint32_t regs[CADENCE_GEM_MAXREG];
116
--
170
--
117
2.7.4
171
2.5.0
118
172
119
173
diff view generated by jsdifflib
New patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
1
2
3
Advertise support of clear-on-read for ISR registers.
4
5
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
9
hw/net/cadence_gem.c | 2 +-
10
1 file changed, 1 insertion(+), 1 deletion(-)
11
12
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/net/cadence_gem.c
15
+++ b/hw/net/cadence_gem.c
16
@@ -XXX,XX +XXX,XX @@ static void gem_reset(DeviceState *d)
17
s->regs[GEM_TXPARTIALSF] = 0x000003ff;
18
s->regs[GEM_RXPARTIALSF] = 0x000003ff;
19
s->regs[GEM_MODID] = s->revision;
20
- s->regs[GEM_DESCONF] = 0x02500111;
21
+ s->regs[GEM_DESCONF] = 0x02D00111;
22
s->regs[GEM_DESCONF2] = 0x2ab10000 | s->jumbo_max_len;
23
s->regs[GEM_DESCONF5] = 0x002f2045;
24
s->regs[GEM_DESCONF6] = GEM_DESCONF6_64B_MASK;
25
--
26
2.5.0
27
28
diff view generated by jsdifflib
New patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
1
2
3
Mask all interrupt on reset.
4
5
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
9
hw/net/cadence_gem.c | 1 +
10
1 file changed, 1 insertion(+)
11
12
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/net/cadence_gem.c
15
+++ b/hw/net/cadence_gem.c
16
@@ -XXX,XX +XXX,XX @@ static void gem_reset(DeviceState *d)
17
s->regs[GEM_DESCONF2] = 0x2ab10000 | s->jumbo_max_len;
18
s->regs[GEM_DESCONF5] = 0x002f2045;
19
s->regs[GEM_DESCONF6] = GEM_DESCONF6_64B_MASK;
20
+ s->regs[GEM_INT_Q1_MASK] = 0x00000CE6;
21
s->regs[GEM_JUMBO_MAX_LEN] = s->jumbo_max_len;
22
23
if (s->num_priority_queues > 1) {
24
--
25
2.5.0
26
27
diff view generated by jsdifflib
New patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
1
2
3
TX_LAST bit should not be set by hardware, its set by guest to inform
4
the last bd of the frame.
5
6
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
7
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
11
hw/net/cadence_gem.c | 6 ------
12
1 file changed, 6 deletions(-)
13
14
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/net/cadence_gem.c
17
+++ b/hw/net/cadence_gem.c
18
@@ -XXX,XX +XXX,XX @@ static inline unsigned tx_desc_get_last(uint32_t *desc)
19
return (desc[1] & DESC_1_TX_LAST) ? 1 : 0;
20
}
21
22
-static inline void tx_desc_set_last(uint32_t *desc)
23
-{
24
- desc[1] |= DESC_1_TX_LAST;
25
-}
26
-
27
static inline unsigned tx_desc_get_length(uint32_t *desc)
28
{
29
return desc[1] & DESC_1_LENGTH;
30
@@ -XXX,XX +XXX,XX @@ static void gem_transmit(CadenceGEMState *s)
31
32
/* read next descriptor */
33
if (tx_desc_get_wrap(desc)) {
34
- tx_desc_set_last(desc);
35
36
if (s->regs[GEM_DMACFG] & GEM_DMACFG_ADDR_64B) {
37
packet_desc_addr = s->regs[GEM_TBQPH];
38
--
39
2.5.0
40
41
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Tong Ho <tong.ho@xilinx.com>
2
2
3
This patch change the filter_send() parameter from CharBackend to MirrorState,
3
Two defects are fixed:
4
we can get more information like vnet_hdr(We use it to support packet with vnet_header).
5
4
6
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
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>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
13
---
9
net/filter-mirror.c | 10 +++++-----
14
hw/net/cadence_gem.c | 26 +++++++++++---------------
10
1 file changed, 5 insertions(+), 5 deletions(-)
15
1 file changed, 11 insertions(+), 15 deletions(-)
11
16
12
diff --git a/net/filter-mirror.c b/net/filter-mirror.c
17
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
13
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
14
--- a/net/filter-mirror.c
19
--- a/hw/net/cadence_gem.c
15
+++ b/net/filter-mirror.c
20
+++ b/hw/net/cadence_gem.c
16
@@ -XXX,XX +XXX,XX @@ typedef struct MirrorState {
21
@@ -XXX,XX +XXX,XX @@
17
SocketReadState rs;
22
#include "qemu/module.h"
18
} MirrorState;
23
#include "sysemu/dma.h"
19
24
#include "net/checksum.h"
20
-static int filter_send(CharBackend *chr_out,
25
+#include "net/eth.h"
21
+static int filter_send(MirrorState *s,
26
22
const struct iovec *iov,
27
#define CADENCE_GEM_ERR_DEBUG 0
23
int iovcnt)
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)
24
{
31
{
25
@@ -XXX,XX +XXX,XX @@ static int filter_send(CharBackend *chr_out,
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)
26
}
39
}
27
40
28
len = htonl(size);
41
/* Accept packets -w- hash match? */
29
- ret = qemu_chr_fe_write_all(chr_out, (uint8_t *)&len, sizeof(len));
42
- if ((packet[0] == 0x01 && (s->regs[GEM_NWCFG] & GEM_NWCFG_MCAST_HASH)) ||
30
+ ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len));
43
- (packet[0] != 0x01 && (s->regs[GEM_NWCFG] & GEM_NWCFG_UCAST_HASH))) {
31
if (ret != sizeof(len)) {
44
+ is_mc = is_multicast_ether_addr(packet);
32
goto err;
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
}
33
}
67
}
34
68
35
buf = g_malloc(size);
69
@@ -XXX,XX +XXX,XX @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
36
iov_to_buf(iov, iovcnt, 0, buf, size);
70
/* Is this destination MAC address "for us" ? */
37
- ret = qemu_chr_fe_write_all(chr_out, (uint8_t *)buf, size);
71
maf = gem_mac_address_filter(s, buf);
38
+ ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)buf, size);
72
if (maf == GEM_RX_REJECT) {
39
g_free(buf);
73
- return -1;
40
if (ret != size) {
74
+ return size; /* no, drop siliently b/c it's not an error */
41
goto err;
42
@@ -XXX,XX +XXX,XX @@ static ssize_t filter_mirror_receive_iov(NetFilterState *nf,
43
MirrorState *s = FILTER_MIRROR(nf);
44
int ret;
45
46
- ret = filter_send(&s->chr_out, iov, iovcnt);
47
+ ret = filter_send(s, iov, iovcnt);
48
if (ret) {
49
error_report("filter mirror send failed(%s)", strerror(-ret));
50
}
75
}
51
@@ -XXX,XX +XXX,XX @@ static ssize_t filter_redirector_receive_iov(NetFilterState *nf,
76
52
int ret;
77
/* Discard packets with receive length error enabled ? */
53
54
if (qemu_chr_fe_backend_connected(&s->chr_out)) {
55
- ret = filter_send(&s->chr_out, iov, iovcnt);
56
+ ret = filter_send(s, iov, iovcnt);
57
if (ret) {
58
error_report("filter redirector send failed(%s)", strerror(-ret));
59
}
60
--
78
--
61
2.7.4
79
2.5.0
62
80
63
81
diff view generated by jsdifflib
New patch
1
The sender of packet will be checked in the qemu_net_queue_purge() but
2
we use NetClientState not its peer when trying to purge the incoming
3
queue in qemu_flush_or_purge_packets(). This will trigger the assert
4
in virtio_net_reset since we can't pass the sender check:
1
5
6
hw/net/virtio-net.c:533: void virtio_net_reset(VirtIODevice *): Assertion
7
`!virtio_net_get_subqueue(nc)->async_tx.elem' failed.
8
#9 0x55a33fa31b78 in virtio_net_reset hw/net/virtio-net.c:533:13
9
#10 0x55a33fc88412 in virtio_reset hw/virtio/virtio.c:1919:9
10
#11 0x55a341d82764 in virtio_bus_reset hw/virtio/virtio-bus.c:95:9
11
#12 0x55a341dba2de in virtio_pci_reset hw/virtio/virtio-pci.c:1824:5
12
#13 0x55a341db3e02 in virtio_pci_common_write hw/virtio/virtio-pci.c:1252:13
13
#14 0x55a33f62117b in memory_region_write_accessor memory.c:496:5
14
#15 0x55a33f6205e4 in access_with_adjusted_size memory.c:557:18
15
#16 0x55a33f61e177 in memory_region_dispatch_write memory.c:1488:16
16
17
Reproducer:
18
https://www.mail-archive.com/qemu-devel@nongnu.org/msg701914.html
19
20
Fix by using the peer.
21
22
Reported-by: "Alexander Bulekov" <alxndr@bu.edu>
23
Acked-by: Alexander Bulekov <alxndr@bu.edu>
24
Fixes: ca77d85e1dbf9 ("net: complete all queued packets on VM stop")
25
Cc: qemu-stable@nongnu.org
26
Signed-off-by: Jason Wang <jasowang@redhat.com>
27
---
28
net/net.c | 2 +-
29
1 file changed, 1 insertion(+), 1 deletion(-)
30
31
diff --git a/net/net.c b/net/net.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/net/net.c
34
+++ b/net/net.c
35
@@ -XXX,XX +XXX,XX @@ void qemu_flush_or_purge_queued_packets(NetClientState *nc, bool purge)
36
qemu_notify_event();
37
} else if (purge) {
38
/* Unable to empty the queue, purge remaining packets */
39
- qemu_net_queue_purge(nc->incoming_queue, nc);
40
+ qemu_net_queue_purge(nc->incoming_queue, nc->peer);
41
}
42
}
43
44
--
45
2.5.0
46
47
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Lukas Straub <lukasstraub2@web.de>
2
2
3
COLO-Proxy just focus on packet payload, so we skip vnet header.
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.
4
7
5
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
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>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
17
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
---
18
---
8
net/colo-compare.c | 8 ++++++--
19
net/colo-compare.c | 3 ++-
9
1 file changed, 6 insertions(+), 2 deletions(-)
20
1 file changed, 2 insertions(+), 1 deletion(-)
10
21
11
diff --git a/net/colo-compare.c b/net/colo-compare.c
22
diff --git a/net/colo-compare.c b/net/colo-compare.c
12
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
13
--- a/net/colo-compare.c
24
--- a/net/colo-compare.c
14
+++ b/net/colo-compare.c
25
+++ b/net/colo-compare.c
15
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_common(Packet *ppkt, Packet *spkt, int offset)
26
@@ -XXX,XX +XXX,XX @@ static void colo_compare_handle_event(void *opaque)
16
sec_ip_src, sec_ip_dst);
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)
17
}
35
}
18
36
19
+ offset = ppkt->vnet_hdr_len + offset;
37
colo_compare_timer_init(s);
20
+
38
- s->event_bh = qemu_bh_new(colo_compare_handle_event, s);
21
if (ppkt->size == spkt->size) {
39
+ s->event_bh = aio_bh_new(ctx, colo_compare_handle_event, s);
22
- return memcmp(ppkt->data + offset, spkt->data + offset,
40
}
23
+ return memcmp(ppkt->data + offset,
41
24
+ spkt->data + offset,
42
static char *compare_get_pri_indev(Object *obj, Error **errp)
25
spkt->size - offset);
26
} else {
27
trace_colo_compare_main("Net packet size are not the same");
28
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_tcp(Packet *spkt, Packet *ppkt)
29
*/
30
if (ptcp->th_off > 5) {
31
ptrdiff_t tcp_offset;
32
+
33
tcp_offset = ppkt->transport_header - (uint8_t *)ppkt->data
34
- + (ptcp->th_off * 4);
35
+ + (ptcp->th_off * 4) - ppkt->vnet_hdr_len;
36
res = colo_packet_compare_common(ppkt, spkt, tcp_offset);
37
} else if (ptcp->th_sum == stcp->th_sum) {
38
res = colo_packet_compare_common(ppkt, spkt, ETH_HLEN);
39
--
43
--
40
2.7.4
44
2.5.0
41
45
42
46
diff view generated by jsdifflib
New patch
1
From: Lukas Straub <lukasstraub2@web.de>
1
2
3
To be able to convert compare_chr_send to a coroutine in the
4
next commit, use qemu_co_sleep_ns if in coroutine.
5
6
Signed-off-by: Lukas Straub <lukasstraub2@web.de>
7
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
8
Reviewed-by: Zhang Chen <chen.zhang@intel.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
13
chardev/char.c | 7 ++++++-
14
1 file changed, 6 insertions(+), 1 deletion(-)
15
16
diff --git a/chardev/char.c b/chardev/char.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/chardev/char.c
19
+++ b/chardev/char.c
20
@@ -XXX,XX +XXX,XX @@
21
#include "qemu/module.h"
22
#include "qemu/option.h"
23
#include "qemu/id.h"
24
+#include "qemu/coroutine.h"
25
26
#include "chardev/char-mux.h"
27
28
@@ -XXX,XX +XXX,XX @@ static int qemu_chr_write_buffer(Chardev *s,
29
retry:
30
res = cc->chr_write(s, buf + *offset, len - *offset);
31
if (res < 0 && errno == EAGAIN && write_all) {
32
- g_usleep(100);
33
+ if (qemu_in_coroutine()) {
34
+ qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, 100000);
35
+ } else {
36
+ g_usleep(100);
37
+ }
38
goto retry;
39
}
40
41
--
42
2.5.0
43
44
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Lukas Straub <lukasstraub2@web.de>
2
2
3
We can use this property flush and send packet with vnet_hdr_len.
3
The chr_out chardev is connected to a filter-redirector
4
4
running in the main loop. qemu_chr_fe_write_all might block
5
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
5
here in compare_chr_send if the (socket-)buffer is full.
6
If another filter-redirector in the main loop want's to
7
send data to chr_pri_in it might also block if the buffer
8
is full. This leads to a deadlock because both event loops
9
get blocked.
10
11
Fix this by converting compare_chr_send to a coroutine and
12
putting the packets in a send queue.
13
14
Signed-off-by: Lukas Straub <lukasstraub2@web.de>
15
Reviewed-by: Zhang Chen <chen.zhang@intel.com>
16
Tested-by: Zhang Chen <chen.zhang@intel.com>
17
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
18
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
---
19
---
8
net/colo-compare.c | 8 ++++++--
20
net/colo-compare.c | 193 ++++++++++++++++++++++++++++++++++++++++-------------
9
net/colo.c | 3 ++-
21
net/colo.c | 7 ++
10
net/colo.h | 4 +++-
22
net/colo.h | 1 +
11
net/filter-rewriter.c | 2 +-
23
3 files changed, 156 insertions(+), 45 deletions(-)
12
4 files changed, 12 insertions(+), 5 deletions(-)
13
24
14
diff --git a/net/colo-compare.c b/net/colo-compare.c
25
diff --git a/net/colo-compare.c b/net/colo-compare.c
15
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
16
--- a/net/colo-compare.c
27
--- a/net/colo-compare.c
17
+++ b/net/colo-compare.c
28
+++ b/net/colo-compare.c
18
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode)
29
@@ -XXX,XX +XXX,XX @@
19
Connection *conn;
30
#include "migration/migration.h"
20
31
#include "util.h"
21
if (mode == PRIMARY_IN) {
32
22
- pkt = packet_new(s->pri_rs.buf, s->pri_rs.packet_len);
33
+#include "block/aio-wait.h"
23
+ pkt = packet_new(s->pri_rs.buf,
34
+#include "qemu/coroutine.h"
24
+ s->pri_rs.packet_len,
35
+
25
+ s->pri_rs.vnet_hdr_len);
36
#define TYPE_COLO_COMPARE "colo-compare"
37
#define COLO_COMPARE(obj) \
38
OBJECT_CHECK(CompareState, (obj), TYPE_COLO_COMPARE)
39
@@ -XXX,XX +XXX,XX @@ static int event_unhandled_count;
40
* |packet | |packet + |packet | |packet +
41
* +--------+ +--------+ +--------+ +--------+
42
*/
43
+
44
+typedef struct SendCo {
45
+ Coroutine *co;
46
+ struct CompareState *s;
47
+ CharBackend *chr;
48
+ GQueue send_list;
49
+ bool notify_remote_frame;
50
+ bool done;
51
+ int ret;
52
+} SendCo;
53
+
54
+typedef struct SendEntry {
55
+ uint32_t size;
56
+ uint32_t vnet_hdr_len;
57
+ uint8_t *buf;
58
+} SendEntry;
59
+
60
typedef struct CompareState {
61
Object parent;
62
63
@@ -XXX,XX +XXX,XX @@ typedef struct CompareState {
64
SocketReadState pri_rs;
65
SocketReadState sec_rs;
66
SocketReadState notify_rs;
67
+ SendCo out_sendco;
68
+ SendCo notify_sendco;
69
bool vnet_hdr;
70
uint32_t compare_timeout;
71
uint32_t expired_scan_cycle;
72
@@ -XXX,XX +XXX,XX @@ enum {
73
74
75
static int compare_chr_send(CompareState *s,
76
- const uint8_t *buf,
77
+ uint8_t *buf,
78
uint32_t size,
79
uint32_t vnet_hdr_len,
80
- bool notify_remote_frame);
81
+ bool notify_remote_frame,
82
+ bool zero_copy);
83
84
static bool packet_matches_str(const char *str,
85
const uint8_t *buf,
86
@@ -XXX,XX +XXX,XX @@ static void notify_remote_frame(CompareState *s)
87
char msg[] = "DO_CHECKPOINT";
88
int ret = 0;
89
90
- ret = compare_chr_send(s, (uint8_t *)msg, strlen(msg), 0, true);
91
+ ret = compare_chr_send(s, (uint8_t *)msg, strlen(msg), 0, true, false);
92
if (ret < 0) {
93
error_report("Notify Xen COLO-frame failed");
94
}
95
@@ -XXX,XX +XXX,XX @@ static void colo_release_primary_pkt(CompareState *s, Packet *pkt)
96
pkt->data,
97
pkt->size,
98
pkt->vnet_hdr_len,
99
- false);
100
+ false,
101
+ true);
102
if (ret < 0) {
103
error_report("colo send primary packet failed");
104
}
105
trace_colo_compare_main("packet same and release packet");
106
- packet_destroy(pkt, NULL);
107
+ packet_destroy_partial(pkt, NULL);
108
}
109
110
/*
111
@@ -XXX,XX +XXX,XX @@ static void colo_compare_connection(void *opaque, void *user_data)
112
}
113
}
114
115
-static int compare_chr_send(CompareState *s,
116
- const uint8_t *buf,
117
- uint32_t size,
118
- uint32_t vnet_hdr_len,
119
- bool notify_remote_frame)
120
+static void coroutine_fn _compare_chr_send(void *opaque)
121
{
122
+ SendCo *sendco = opaque;
123
+ CompareState *s = sendco->s;
124
int ret = 0;
125
- uint32_t len = htonl(size);
126
127
- if (!size) {
128
- return 0;
129
- }
130
+ while (!g_queue_is_empty(&sendco->send_list)) {
131
+ SendEntry *entry = g_queue_pop_tail(&sendco->send_list);
132
+ uint32_t len = htonl(entry->size);
133
134
- if (notify_remote_frame) {
135
- ret = qemu_chr_fe_write_all(&s->chr_notify_dev,
136
- (uint8_t *)&len,
137
- sizeof(len));
138
- } else {
139
- ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len));
140
- }
141
+ ret = qemu_chr_fe_write_all(sendco->chr, (uint8_t *)&len, sizeof(len));
142
143
- if (ret != sizeof(len)) {
144
- goto err;
145
- }
146
+ if (ret != sizeof(len)) {
147
+ g_free(entry->buf);
148
+ g_slice_free(SendEntry, entry);
149
+ goto err;
150
+ }
151
152
- if (s->vnet_hdr) {
153
- /*
154
- * We send vnet header len make other module(like filter-redirector)
155
- * know how to parse net packet correctly.
156
- */
157
- len = htonl(vnet_hdr_len);
158
+ if (!sendco->notify_remote_frame && s->vnet_hdr) {
159
+ /*
160
+ * We send vnet header len make other module(like filter-redirector)
161
+ * know how to parse net packet correctly.
162
+ */
163
+ len = htonl(entry->vnet_hdr_len);
164
165
- if (!notify_remote_frame) {
166
- ret = qemu_chr_fe_write_all(&s->chr_out,
167
+ ret = qemu_chr_fe_write_all(sendco->chr,
168
(uint8_t *)&len,
169
sizeof(len));
170
+
171
+ if (ret != sizeof(len)) {
172
+ g_free(entry->buf);
173
+ g_slice_free(SendEntry, entry);
174
+ goto err;
175
+ }
176
}
177
178
- if (ret != sizeof(len)) {
179
+ ret = qemu_chr_fe_write_all(sendco->chr,
180
+ (uint8_t *)entry->buf,
181
+ entry->size);
182
+
183
+ if (ret != entry->size) {
184
+ g_free(entry->buf);
185
+ g_slice_free(SendEntry, entry);
186
goto err;
187
}
188
+
189
+ g_free(entry->buf);
190
+ g_slice_free(SendEntry, entry);
191
}
192
193
+ sendco->ret = 0;
194
+ goto out;
195
+
196
+err:
197
+ while (!g_queue_is_empty(&sendco->send_list)) {
198
+ SendEntry *entry = g_queue_pop_tail(&sendco->send_list);
199
+ g_free(entry->buf);
200
+ g_slice_free(SendEntry, entry);
201
+ }
202
+ sendco->ret = ret < 0 ? ret : -EIO;
203
+out:
204
+ sendco->co = NULL;
205
+ sendco->done = true;
206
+ aio_wait_kick();
207
+}
208
+
209
+static int compare_chr_send(CompareState *s,
210
+ uint8_t *buf,
211
+ uint32_t size,
212
+ uint32_t vnet_hdr_len,
213
+ bool notify_remote_frame,
214
+ bool zero_copy)
215
+{
216
+ SendCo *sendco;
217
+ SendEntry *entry;
218
+
219
if (notify_remote_frame) {
220
- ret = qemu_chr_fe_write_all(&s->chr_notify_dev,
221
- (uint8_t *)buf,
222
- size);
223
+ sendco = &s->notify_sendco;
26
} else {
224
} else {
27
- pkt = packet_new(s->sec_rs.buf, s->sec_rs.packet_len);
225
- ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)buf, size);
28
+ pkt = packet_new(s->sec_rs.buf,
226
+ sendco = &s->out_sendco;
29
+ s->sec_rs.packet_len,
227
}
30
+ s->sec_rs.vnet_hdr_len);
228
31
}
229
- if (ret != size) {
32
230
- goto err;
33
if (parse_packet_early(pkt)) {
231
+ if (!size) {
232
+ return 0;
233
}
234
235
- return 0;
236
+ entry = g_slice_new(SendEntry);
237
+ entry->size = size;
238
+ entry->vnet_hdr_len = vnet_hdr_len;
239
+ if (zero_copy) {
240
+ entry->buf = buf;
241
+ } else {
242
+ entry->buf = g_malloc(size);
243
+ memcpy(entry->buf, buf, size);
244
+ }
245
+ g_queue_push_head(&sendco->send_list, entry);
246
+
247
+ if (sendco->done) {
248
+ sendco->co = qemu_coroutine_create(_compare_chr_send, sendco);
249
+ sendco->done = false;
250
+ qemu_coroutine_enter(sendco->co);
251
+ if (sendco->done) {
252
+ /* report early errors */
253
+ return sendco->ret;
254
+ }
255
+ }
256
257
-err:
258
- return ret < 0 ? ret : -EIO;
259
+ /* assume success */
260
+ return 0;
261
}
262
263
static int compare_chr_can_read(void *opaque)
264
@@ -XXX,XX +XXX,XX @@ static void compare_pri_rs_finalize(SocketReadState *pri_rs)
265
pri_rs->buf,
266
pri_rs->packet_len,
267
pri_rs->vnet_hdr_len,
268
+ false,
269
false);
270
} else {
271
/* compare packet in the specified connection */
272
@@ -XXX,XX +XXX,XX @@ static void compare_notify_rs_finalize(SocketReadState *notify_rs)
273
if (packet_matches_str("COLO_USERSPACE_PROXY_INIT",
274
notify_rs->buf,
275
notify_rs->packet_len)) {
276
- ret = compare_chr_send(s, (uint8_t *)msg, strlen(msg), 0, true);
277
+ ret = compare_chr_send(s, (uint8_t *)msg, strlen(msg), 0, true, false);
278
if (ret < 0) {
279
error_report("Notify Xen COLO-frame INIT failed");
280
}
281
@@ -XXX,XX +XXX,XX @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
282
283
QTAILQ_INSERT_TAIL(&net_compares, s, next);
284
285
+ s->out_sendco.s = s;
286
+ s->out_sendco.chr = &s->chr_out;
287
+ s->out_sendco.notify_remote_frame = false;
288
+ s->out_sendco.done = true;
289
+ g_queue_init(&s->out_sendco.send_list);
290
+
291
+ if (s->notify_dev) {
292
+ s->notify_sendco.s = s;
293
+ s->notify_sendco.chr = &s->chr_notify_dev;
294
+ s->notify_sendco.notify_remote_frame = true;
295
+ s->notify_sendco.done = true;
296
+ g_queue_init(&s->notify_sendco.send_list);
297
+ }
298
+
299
g_queue_init(&s->conn_list);
300
301
qemu_mutex_init(&event_mtx);
302
@@ -XXX,XX +XXX,XX @@ static void colo_flush_packets(void *opaque, void *user_data)
303
pkt->data,
304
pkt->size,
305
pkt->vnet_hdr_len,
306
- false);
307
- packet_destroy(pkt, NULL);
308
+ false,
309
+ true);
310
+ packet_destroy_partial(pkt, NULL);
311
}
312
while (!g_queue_is_empty(&conn->secondary_list)) {
313
pkt = g_queue_pop_head(&conn->secondary_list);
314
@@ -XXX,XX +XXX,XX @@ static void colo_compare_finalize(Object *obj)
315
}
316
}
317
318
+ AioContext *ctx = iothread_get_aio_context(s->iothread);
319
+ aio_context_acquire(ctx);
320
+ AIO_WAIT_WHILE(ctx, !s->out_sendco.done);
321
+ if (s->notify_dev) {
322
+ AIO_WAIT_WHILE(ctx, !s->notify_sendco.done);
323
+ }
324
+ aio_context_release(ctx);
325
+
326
/* Release all unhandled packets after compare thead exited */
327
g_queue_foreach(&s->conn_list, colo_flush_packets, s);
328
+ AIO_WAIT_WHILE(NULL, !s->out_sendco.done);
329
330
g_queue_clear(&s->conn_list);
331
+ g_queue_clear(&s->out_sendco.send_list);
332
+ if (s->notify_dev) {
333
+ g_queue_clear(&s->notify_sendco.send_list);
334
+ }
335
336
if (s->connection_track_table) {
337
g_hash_table_destroy(s->connection_track_table);
34
diff --git a/net/colo.c b/net/colo.c
338
diff --git a/net/colo.c b/net/colo.c
35
index XXXXXXX..XXXXXXX 100644
339
index XXXXXXX..XXXXXXX 100644
36
--- a/net/colo.c
340
--- a/net/colo.c
37
+++ b/net/colo.c
341
+++ b/net/colo.c
38
@@ -XXX,XX +XXX,XX @@ void connection_destroy(void *opaque)
342
@@ -XXX,XX +XXX,XX @@ void packet_destroy(void *opaque, void *user_data)
39
g_slice_free(Connection, conn);
343
g_slice_free(Packet, pkt);
40
}
344
}
41
345
42
-Packet *packet_new(const void *data, int size)
346
+void packet_destroy_partial(void *opaque, void *user_data)
43
+Packet *packet_new(const void *data, int size, int vnet_hdr_len)
347
+{
44
{
348
+ Packet *pkt = opaque;
45
Packet *pkt = g_slice_new(Packet);
349
+
46
350
+ g_slice_free(Packet, pkt);
47
pkt->data = g_memdup(data, size);
351
+}
48
pkt->size = size;
352
+
49
pkt->creation_ms = qemu_clock_get_ms(QEMU_CLOCK_HOST);
353
/*
50
+ pkt->vnet_hdr_len = vnet_hdr_len;
354
* Clear hashtable, stop this hash growing really huge
51
355
*/
52
return pkt;
53
}
54
diff --git a/net/colo.h b/net/colo.h
356
diff --git a/net/colo.h b/net/colo.h
55
index XXXXXXX..XXXXXXX 100644
357
index XXXXXXX..XXXXXXX 100644
56
--- a/net/colo.h
358
--- a/net/colo.h
57
+++ b/net/colo.h
359
+++ b/net/colo.h
58
@@ -XXX,XX +XXX,XX @@ typedef struct Packet {
360
@@ -XXX,XX +XXX,XX @@ bool connection_has_tracked(GHashTable *connection_track_table,
59
int size;
60
/* Time of packet creation, in wall clock ms */
61
int64_t creation_ms;
62
+ /* Get vnet_hdr_len from filter */
63
+ uint32_t vnet_hdr_len;
64
} Packet;
65
66
typedef struct ConnectionKey {
67
@@ -XXX,XX +XXX,XX @@ Connection *connection_get(GHashTable *connection_track_table,
68
ConnectionKey *key,
69
GQueue *conn_list);
70
void connection_hashtable_reset(GHashTable *connection_track_table);
361
void connection_hashtable_reset(GHashTable *connection_track_table);
71
-Packet *packet_new(const void *data, int size);
362
Packet *packet_new(const void *data, int size, int vnet_hdr_len);
72
+Packet *packet_new(const void *data, int size, int vnet_hdr_len);
73
void packet_destroy(void *opaque, void *user_data);
363
void packet_destroy(void *opaque, void *user_data);
74
364
+void packet_destroy_partial(void *opaque, void *user_data);
75
#endif /* QEMU_COLO_PROXY_H */
365
76
diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c
366
#endif /* NET_COLO_H */
77
index XXXXXXX..XXXXXXX 100644
78
--- a/net/filter-rewriter.c
79
+++ b/net/filter-rewriter.c
80
@@ -XXX,XX +XXX,XX @@ static ssize_t colo_rewriter_receive_iov(NetFilterState *nf,
81
char *buf = g_malloc0(size);
82
83
iov_to_buf(iov, iovcnt, 0, buf, size);
84
- pkt = packet_new(buf, size);
85
+ pkt = packet_new(buf, size, 0);
86
g_free(buf);
87
88
/*
89
--
367
--
90
2.7.4
368
2.5.0
91
369
92
370
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Lukas Straub <lukasstraub2@web.de>
2
2
3
Make colo-compare and filter-rewriter can parse vnet packet.
3
Else the log will be flooded if there is a lot of network
4
traffic.
4
5
5
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
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>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
---
12
---
8
net/colo.c | 6 +++---
13
net/colo-compare.c | 10 ++++++----
9
1 file changed, 3 insertions(+), 3 deletions(-)
14
1 file changed, 6 insertions(+), 4 deletions(-)
10
15
11
diff --git a/net/colo.c b/net/colo.c
16
diff --git a/net/colo-compare.c b/net/colo-compare.c
12
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
13
--- a/net/colo.c
18
--- a/net/colo-compare.c
14
+++ b/net/colo.c
19
+++ b/net/colo-compare.c
15
@@ -XXX,XX +XXX,XX @@ int parse_packet_early(Packet *pkt)
20
@@ -XXX,XX +XXX,XX @@ sec:
16
{
21
g_queue_push_head(&conn->primary_list, ppkt);
17
int network_length;
22
g_queue_push_head(&conn->secondary_list, spkt);
18
static const uint8_t vlan[] = {0x81, 0x00};
23
19
- uint8_t *data = pkt->data;
24
- qemu_hexdump((char *)ppkt->data, stderr,
20
+ uint8_t *data = pkt->data + pkt->vnet_hdr_len;
25
- "colo-compare ppkt", ppkt->size);
21
uint16_t l3_proto;
26
- qemu_hexdump((char *)spkt->data, stderr,
22
ssize_t l2hdr_len = eth_get_l2_hdr_length(data);
27
- "colo-compare spkt", spkt->size);
23
28
+ if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) {
24
- if (pkt->size < ETH_HLEN) {
29
+ qemu_hexdump((char *)ppkt->data, stderr,
25
+ if (pkt->size < ETH_HLEN + pkt->vnet_hdr_len) {
30
+ "colo-compare ppkt", ppkt->size);
26
trace_colo_proxy_main("pkt->size < ETH_HLEN");
31
+ qemu_hexdump((char *)spkt->data, stderr,
27
return 1;
32
+ "colo-compare spkt", spkt->size);
28
}
33
+ }
29
@@ -XXX,XX +XXX,XX @@ int parse_packet_early(Packet *pkt)
34
30
}
35
colo_compare_inconsistency_notify(s);
31
32
network_length = pkt->ip->ip_hl * 4;
33
- if (pkt->size < l2hdr_len + network_length) {
34
+ if (pkt->size < l2hdr_len + network_length + pkt->vnet_hdr_len) {
35
trace_colo_proxy_main("pkt->size < network_header + network_length");
36
return 1;
37
}
36
}
38
--
37
--
39
2.7.4
38
2.5.0
40
39
41
40
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Lukas Straub <lukasstraub2@web.de>
2
2
3
We add a flag to decide whether net_fill_rstate() need read
3
If the colo-compare object is removed before failover and a
4
the vnet_hdr_len or not.
4
checkpoint happens, qemu crashes because it tries to lock
5
the destroyed event_mtx in colo_notify_compares_event.
5
6
6
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
7
Fix this by checking if everything is initialized by
7
Suggested-by: Jason Wang <jasowang@redhat.com>
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>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
22
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
23
---
10
include/net/net.h | 9 +++++++--
24
net/colo-compare.c | 35 +++++++++++++++++++++++++++++------
11
net/colo-compare.c | 4 ++--
25
1 file changed, 29 insertions(+), 6 deletions(-)
12
net/filter-mirror.c | 2 +-
13
net/net.c | 36 ++++++++++++++++++++++++++++++++----
14
net/socket.c | 8 ++++----
15
5 files changed, 46 insertions(+), 13 deletions(-)
16
26
17
diff --git a/include/net/net.h b/include/net/net.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/net/net.h
20
+++ b/include/net/net.h
21
@@ -XXX,XX +XXX,XX @@ typedef struct NICState {
22
} NICState;
23
24
struct SocketReadState {
25
- int state; /* 0 = getting length, 1 = getting data */
26
+ /* 0 = getting length, 1 = getting vnet header length, 2 = getting data */
27
+ int state;
28
+ /* This flag decide whether to read the vnet_hdr_len field */
29
+ bool vnet_hdr;
30
uint32_t index;
31
uint32_t packet_len;
32
+ uint32_t vnet_hdr_len;
33
uint8_t buf[NET_BUFSIZE];
34
SocketReadStateFinalize *finalize;
35
};
36
@@ -XXX,XX +XXX,XX @@ ssize_t qemu_deliver_packet_iov(NetClientState *sender,
37
void print_net_client(Monitor *mon, NetClientState *nc);
38
void hmp_info_network(Monitor *mon, const QDict *qdict);
39
void net_socket_rs_init(SocketReadState *rs,
40
- SocketReadStateFinalize *finalize);
41
+ SocketReadStateFinalize *finalize,
42
+ bool vnet_hdr);
43
44
/* NIC info */
45
46
diff --git a/net/colo-compare.c b/net/colo-compare.c
27
diff --git a/net/colo-compare.c b/net/colo-compare.c
47
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
48
--- a/net/colo-compare.c
29
--- a/net/colo-compare.c
49
+++ b/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)
50
@@ -XXX,XX +XXX,XX @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
61
@@ -XXX,XX +XXX,XX @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
51
return;
62
s->vnet_hdr);
52
}
63
}
53
64
54
- net_socket_rs_init(&s->pri_rs, compare_pri_rs_finalize);
65
+ qemu_mutex_lock(&colo_compare_mutex);
55
- net_socket_rs_init(&s->sec_rs, compare_sec_rs_finalize);
66
+ if (!colo_compare_active) {
56
+ net_socket_rs_init(&s->pri_rs, compare_pri_rs_finalize, false);
67
+ qemu_mutex_init(&event_mtx);
57
+ net_socket_rs_init(&s->sec_rs, compare_sec_rs_finalize, false);
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)
58
77
59
g_queue_init(&s->conn_list);
78
g_queue_init(&s->conn_list);
60
79
61
diff --git a/net/filter-mirror.c b/net/filter-mirror.c
80
- qemu_mutex_init(&event_mtx);
62
index XXXXXXX..XXXXXXX 100644
81
- qemu_cond_init(&event_complete_cond);
63
--- a/net/filter-mirror.c
82
-
64
+++ b/net/filter-mirror.c
83
s->connection_track_table = g_hash_table_new_full(connection_key_hash,
65
@@ -XXX,XX +XXX,XX @@ static void filter_redirector_setup(NetFilterState *nf, Error **errp)
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;
66
}
95
}
67
}
96
}
68
97
+ if (QTAILQ_EMPTY(&net_compares)) {
69
- net_socket_rs_init(&s->rs, redirector_rs_finalize);
98
+ colo_compare_active = false;
70
+ net_socket_rs_init(&s->rs, redirector_rs_finalize, false);
99
+ qemu_mutex_destroy(&event_mtx);
71
100
+ qemu_cond_destroy(&event_complete_cond);
72
if (s->indev) {
101
+ }
73
chr = qemu_chr_find(s->indev);
102
+ qemu_mutex_unlock(&colo_compare_mutex);
74
diff --git a/net/net.c b/net/net.c
103
75
index XXXXXXX..XXXXXXX 100644
104
AioContext *ctx = iothread_get_aio_context(s->iothread);
76
--- a/net/net.c
105
aio_context_acquire(ctx);
77
+++ b/net/net.c
106
@@ -XXX,XX +XXX,XX @@ static void colo_compare_finalize(Object *obj)
78
@@ -XXX,XX +XXX,XX @@ QemuOptsList qemu_net_opts = {
107
object_unref(OBJECT(s->iothread));
79
};
108
}
80
109
81
void net_socket_rs_init(SocketReadState *rs,
110
- qemu_mutex_destroy(&event_mtx);
82
- SocketReadStateFinalize *finalize)
111
- qemu_cond_destroy(&event_complete_cond);
83
+ SocketReadStateFinalize *finalize,
112
-
84
+ bool vnet_hdr)
113
g_free(s->pri_indev);
85
{
114
g_free(s->sec_indev);
86
rs->state = 0;
115
g_free(s->outdev);
87
+ rs->vnet_hdr = vnet_hdr;
116
g_free(s->notify_dev);
88
rs->index = 0;
89
rs->packet_len = 0;
90
+ rs->vnet_hdr_len = 0;
91
memset(rs->buf, 0, sizeof(rs->buf));
92
rs->finalize = finalize;
93
}
117
}
94
@@ -XXX,XX +XXX,XX @@ int net_fill_rstate(SocketReadState *rs, const uint8_t *buf, int size)
118
95
unsigned int l;
119
+static void __attribute__((__constructor__)) colo_compare_init_globals(void)
96
120
+{
97
while (size > 0) {
121
+ colo_compare_active = false;
98
- /* reassemble a packet from the network */
122
+ qemu_mutex_init(&colo_compare_mutex);
99
- switch (rs->state) { /* 0 = getting length, 1 = getting data */
123
+}
100
+ /* Reassemble a packet from the network.
124
+
101
+ * 0 = getting length.
125
static const TypeInfo colo_compare_info = {
102
+ * 1 = getting vnet header length.
126
.name = TYPE_COLO_COMPARE,
103
+ * 2 = getting data.
127
.parent = TYPE_OBJECT,
104
+ */
105
+ switch (rs->state) {
106
case 0:
107
l = 4 - rs->index;
108
if (l > size) {
109
@@ -XXX,XX +XXX,XX @@ int net_fill_rstate(SocketReadState *rs, const uint8_t *buf, int size)
110
/* got length */
111
rs->packet_len = ntohl(*(uint32_t *)rs->buf);
112
rs->index = 0;
113
- rs->state = 1;
114
+ if (rs->vnet_hdr) {
115
+ rs->state = 1;
116
+ } else {
117
+ rs->state = 2;
118
+ rs->vnet_hdr_len = 0;
119
+ }
120
}
121
break;
122
case 1:
123
+ l = 4 - rs->index;
124
+ if (l > size) {
125
+ l = size;
126
+ }
127
+ memcpy(rs->buf + rs->index, buf, l);
128
+ buf += l;
129
+ size -= l;
130
+ rs->index += l;
131
+ if (rs->index == 4) {
132
+ /* got vnet header length */
133
+ rs->vnet_hdr_len = ntohl(*(uint32_t *)rs->buf);
134
+ rs->index = 0;
135
+ rs->state = 2;
136
+ }
137
+ break;
138
+ case 2:
139
l = rs->packet_len - rs->index;
140
if (l > size) {
141
l = size;
142
diff --git a/net/socket.c b/net/socket.c
143
index XXXXXXX..XXXXXXX 100644
144
--- a/net/socket.c
145
+++ b/net/socket.c
146
@@ -XXX,XX +XXX,XX @@ static void net_socket_send(void *opaque)
147
closesocket(s->fd);
148
149
s->fd = -1;
150
- net_socket_rs_init(&s->rs, net_socket_rs_finalize);
151
+ net_socket_rs_init(&s->rs, net_socket_rs_finalize, false);
152
s->nc.link_down = true;
153
memset(s->nc.info_str, 0, sizeof(s->nc.info_str));
154
155
@@ -XXX,XX +XXX,XX @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer,
156
s->fd = fd;
157
s->listen_fd = -1;
158
s->send_fn = net_socket_send_dgram;
159
- net_socket_rs_init(&s->rs, net_socket_rs_finalize);
160
+ net_socket_rs_init(&s->rs, net_socket_rs_finalize, false);
161
net_socket_read_poll(s, true);
162
163
/* mcast: save bound address as dst */
164
@@ -XXX,XX +XXX,XX @@ static NetSocketState *net_socket_fd_init_stream(NetClientState *peer,
165
166
s->fd = fd;
167
s->listen_fd = -1;
168
- net_socket_rs_init(&s->rs, net_socket_rs_finalize);
169
+ net_socket_rs_init(&s->rs, net_socket_rs_finalize, false);
170
171
/* Disable Nagle algorithm on TCP sockets to reduce latency */
172
socket_set_nodelay(fd);
173
@@ -XXX,XX +XXX,XX @@ static int net_socket_listen_init(NetClientState *peer,
174
s->fd = -1;
175
s->listen_fd = fd;
176
s->nc.link_down = true;
177
- net_socket_rs_init(&s->rs, net_socket_rs_finalize);
178
+ net_socket_rs_init(&s->rs, net_socket_rs_finalize, false);
179
180
qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s);
181
return 0;
182
--
128
--
183
2.7.4
129
2.5.0
184
130
185
131
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Lukas Straub <lukasstraub2@web.de>
2
2
3
We add the vnet_hdr_support option for colo-compare, default is disabled.
3
In colo_compare_complete, insert CompareState into net_compares
4
If you use virtio-net-pci or other driver needs vnet_hdr, please enable it.
4
only after everything has been initialized.
5
You can use it for example:
5
In colo_compare_finalize, remove CompareState from net_compares
6
-object colo-compare,id=comp0,primary_in=compare0-0,secondary_in=compare1,outdev=compare_out0,vnet_hdr_support
6
before anything is deinitialized.
7
7
8
COLO-compare can get vnet header length from filter,
8
Signed-off-by: Lukas Straub <lukasstraub2@web.de>
9
Add vnet_hdr_len to struct packet and output packet with
9
Reviewed-by: Zhang Chen <chen.zhang@intel.com>
10
the vnet_hdr_len.
10
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
11
12
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
13
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
14
---
12
---
15
net/colo-compare.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++-------
13
net/colo-compare.c | 45 +++++++++++++++++++++++----------------------
16
qemu-options.hx | 4 ++--
14
1 file changed, 23 insertions(+), 22 deletions(-)
17
2 files changed, 55 insertions(+), 9 deletions(-)
18
15
19
diff --git a/net/colo-compare.c b/net/colo-compare.c
16
diff --git a/net/colo-compare.c b/net/colo-compare.c
20
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
21
--- a/net/colo-compare.c
18
--- a/net/colo-compare.c
22
+++ b/net/colo-compare.c
19
+++ b/net/colo-compare.c
23
@@ -XXX,XX +XXX,XX @@ typedef struct CompareState {
20
@@ -XXX,XX +XXX,XX @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
24
CharBackend chr_out;
21
s->vnet_hdr);
25
SocketReadState pri_rs;
26
SocketReadState sec_rs;
27
+ bool vnet_hdr;
28
29
/* connection list: the connections belonged to this NIC could be found
30
* in this list.
31
@@ -XXX,XX +XXX,XX @@ enum {
32
33
static int compare_chr_send(CompareState *s,
34
const uint8_t *buf,
35
- uint32_t size);
36
+ uint32_t size,
37
+ uint32_t vnet_hdr_len);
38
39
static gint seq_sorter(Packet *a, Packet *b, gpointer data)
40
{
41
@@ -XXX,XX +XXX,XX @@ static void colo_compare_connection(void *opaque, void *user_data)
42
}
43
44
if (result) {
45
- ret = compare_chr_send(s, pkt->data, pkt->size);
46
+ ret = compare_chr_send(s,
47
+ pkt->data,
48
+ pkt->size,
49
+ pkt->vnet_hdr_len);
50
if (ret < 0) {
51
error_report("colo_send_primary_packet failed");
52
}
53
@@ -XXX,XX +XXX,XX @@ static void colo_compare_connection(void *opaque, void *user_data)
54
55
static int compare_chr_send(CompareState *s,
56
const uint8_t *buf,
57
- uint32_t size)
58
+ uint32_t size,
59
+ uint32_t vnet_hdr_len)
60
{
61
int ret = 0;
62
uint32_t len = htonl(size);
63
@@ -XXX,XX +XXX,XX @@ static int compare_chr_send(CompareState *s,
64
goto err;
65
}
22
}
66
23
67
+ if (s->vnet_hdr) {
24
- qemu_mutex_lock(&colo_compare_mutex);
68
+ /*
25
- if (!colo_compare_active) {
69
+ * We send vnet header len make other module(like filter-redirector)
26
- qemu_mutex_init(&event_mtx);
70
+ * know how to parse net packet correctly.
27
- qemu_cond_init(&event_complete_cond);
71
+ */
28
- colo_compare_active = true;
72
+ len = htonl(vnet_hdr_len);
29
- }
73
+ ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len));
30
- QTAILQ_INSERT_TAIL(&net_compares, s, next);
74
+ if (ret != sizeof(len)) {
31
- qemu_mutex_unlock(&colo_compare_mutex);
75
+ goto err;
32
-
76
+ }
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);
77
+ }
82
+ }
78
+
83
+
79
ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)buf, size);
84
+ if (s->iothread) {
80
if (ret != size) {
85
+ colo_compare_timer_del(s);
81
goto err;
86
+ }
82
@@ -XXX,XX +XXX,XX @@ static void compare_set_outdev(Object *obj, const char *value, Error **errp)
83
s->outdev = g_strdup(value);
84
}
85
86
+static bool compare_get_vnet_hdr(Object *obj, Error **errp)
87
+{
88
+ CompareState *s = COLO_COMPARE(obj);
89
+
87
+
90
+ return s->vnet_hdr;
88
+ qemu_bh_delete(s->event_bh);
91
+}
92
+
89
+
93
+static void compare_set_vnet_hdr(Object *obj,
90
AioContext *ctx = iothread_get_aio_context(s->iothread);
94
+ bool value,
91
aio_context_acquire(ctx);
95
+ Error **errp)
92
AIO_WAIT_WHILE(ctx, !s->out_sendco.done);
96
+{
97
+ CompareState *s = COLO_COMPARE(obj);
98
+
99
+ s->vnet_hdr = value;
100
+}
101
+
102
static void compare_pri_rs_finalize(SocketReadState *pri_rs)
103
{
104
CompareState *s = container_of(pri_rs, CompareState, pri_rs);
105
106
if (packet_enqueue(s, PRIMARY_IN)) {
107
trace_colo_compare_main("primary: unsupported packet in");
108
- compare_chr_send(s, pri_rs->buf, pri_rs->packet_len);
109
+ compare_chr_send(s,
110
+ pri_rs->buf,
111
+ pri_rs->packet_len,
112
+ pri_rs->vnet_hdr_len);
113
} else {
114
/* compare connection */
115
g_queue_foreach(&s->conn_list, colo_compare_connection, s);
116
@@ -XXX,XX +XXX,XX @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
117
return;
118
}
119
120
- net_socket_rs_init(&s->pri_rs, compare_pri_rs_finalize, false);
121
- net_socket_rs_init(&s->sec_rs, compare_sec_rs_finalize, false);
122
+ net_socket_rs_init(&s->pri_rs, compare_pri_rs_finalize, s->vnet_hdr);
123
+ net_socket_rs_init(&s->sec_rs, compare_sec_rs_finalize, s->vnet_hdr);
124
125
g_queue_init(&s->conn_list);
126
127
@@ -XXX,XX +XXX,XX @@ static void colo_flush_packets(void *opaque, void *user_data)
128
129
while (!g_queue_is_empty(&conn->primary_list)) {
130
pkt = g_queue_pop_head(&conn->primary_list);
131
- compare_chr_send(s, pkt->data, pkt->size);
132
+ compare_chr_send(s,
133
+ pkt->data,
134
+ pkt->size,
135
+ pkt->vnet_hdr_len);
136
packet_destroy(pkt, NULL);
137
}
138
while (!g_queue_is_empty(&conn->secondary_list)) {
139
@@ -XXX,XX +XXX,XX @@ static void colo_compare_class_init(ObjectClass *oc, void *data)
140
141
static void colo_compare_init(Object *obj)
142
{
143
+ CompareState *s = COLO_COMPARE(obj);
144
+
145
object_property_add_str(obj, "primary_in",
146
compare_get_pri_indev, compare_set_pri_indev,
147
NULL);
148
@@ -XXX,XX +XXX,XX @@ static void colo_compare_init(Object *obj)
149
object_property_add_str(obj, "outdev",
150
compare_get_outdev, compare_set_outdev,
151
NULL);
152
+
153
+ s->vnet_hdr = false;
154
+ object_property_add_bool(obj, "vnet_hdr_support", compare_get_vnet_hdr,
155
+ compare_set_vnet_hdr, NULL);
156
}
157
158
static void colo_compare_finalize(Object *obj)
159
diff --git a/qemu-options.hx b/qemu-options.hx
160
index XXXXXXX..XXXXXXX 100644
161
--- a/qemu-options.hx
162
+++ b/qemu-options.hx
163
@@ -XXX,XX +XXX,XX @@ Dump the network traffic on netdev @var{dev} to the file specified by
164
The file format is libpcap, so it can be analyzed with tools such as tcpdump
165
or Wireshark.
166
167
-@item -object colo-compare,id=@var{id},primary_in=@var{chardevid},secondary_in=@var{chardevid},
168
-outdev=@var{chardevid}
169
+@item -object colo-compare,id=@var{id},primary_in=@var{chardevid},secondary_in=@var{chardevid},outdev=@var{chardevid}[,vnet_hdr_support]
170
171
Colo-compare gets packet from primary_in@var{chardevid} and secondary_in@var{chardevid}, than compare primary packet with
172
secondary packet. If the packets are same, we will output primary
173
packet to outdev@var{chardevid}, else we will notify colo-frame
174
do checkpoint and send primary packet to outdev@var{chardevid}.
175
+if it has the vnet_hdr_support flag, colo compare will send/recv packet with vnet_hdr_len.
176
177
we must use it with the help of filter-mirror and filter-redirector.
178
179
--
93
--
180
2.7.4
94
2.5.0
181
95
182
96
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Derek Su <dereksu@qnap.com>
2
2
3
This patch change the compare_chr_send() parameter from CharBackend to CompareState,
3
The patch is to fix the "pkt" memory leak in packet_enqueue().
4
we can get more information like vnet_hdr(We use it to support packet with vnet_header).
4
The allocated "pkt" needs to be freed if the colo compare
5
primary or secondary queue is too big.
5
6
6
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
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>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
14
---
9
net/colo-compare.c | 14 +++++++-------
15
net/colo-compare.c | 23 +++++++++++++++--------
10
1 file changed, 7 insertions(+), 7 deletions(-)
16
net/trace-events | 1 +
17
2 files changed, 16 insertions(+), 8 deletions(-)
11
18
12
diff --git a/net/colo-compare.c b/net/colo-compare.c
19
diff --git a/net/colo-compare.c b/net/colo-compare.c
13
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
14
--- a/net/colo-compare.c
21
--- a/net/colo-compare.c
15
+++ b/net/colo-compare.c
22
+++ b/net/colo-compare.c
16
@@ -XXX,XX +XXX,XX @@ enum {
23
@@ -XXX,XX +XXX,XX @@ enum {
17
SECONDARY_IN,
24
SECONDARY_IN,
18
};
25
};
19
26
20
-static int compare_chr_send(CharBackend *out,
27
+static const char *colo_mode[] = {
21
+static int compare_chr_send(CompareState *s,
28
+ [PRIMARY_IN] = "primary",
22
const uint8_t *buf,
29
+ [SECONDARY_IN] = "secondary",
23
uint32_t size);
30
+};
24
31
25
@@ -XXX,XX +XXX,XX @@ static void colo_compare_connection(void *opaque, void *user_data)
32
static int compare_chr_send(CompareState *s,
26
}
33
uint8_t *buf,
27
34
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode, Connection **con)
28
if (result) {
35
ConnectionKey key;
29
- ret = compare_chr_send(&s->chr_out, pkt->data, pkt->size);
36
Packet *pkt = NULL;
30
+ ret = compare_chr_send(s, pkt->data, pkt->size);
37
Connection *conn;
31
if (ret < 0) {
38
+ int ret;
32
error_report("colo_send_primary_packet failed");
39
33
}
40
if (mode == PRIMARY_IN) {
34
@@ -XXX,XX +XXX,XX @@ static void colo_compare_connection(void *opaque, void *user_data)
41
pkt = packet_new(s->pri_rs.buf,
42
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode, Connection **con)
35
}
43
}
36
}
44
37
45
if (mode == PRIMARY_IN) {
38
-static int compare_chr_send(CharBackend *out,
46
- if (!colo_insert_packet(&conn->primary_list, pkt, &conn->pack)) {
39
+static int compare_chr_send(CompareState *s,
47
- error_report("colo compare primary queue size too big,"
40
const uint8_t *buf,
48
- "drop packet");
41
uint32_t size)
49
- }
42
{
50
+ ret = colo_insert_packet(&conn->primary_list, pkt, &conn->pack);
43
@@ -XXX,XX +XXX,XX @@ static int compare_chr_send(CharBackend *out,
51
} else {
44
return 0;
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);
45
}
57
}
46
58
+
47
- ret = qemu_chr_fe_write_all(out, (uint8_t *)&len, sizeof(len));
59
+ if (!ret) {
48
+ ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len));
60
+ trace_colo_compare_drop_packet(colo_mode[mode],
49
if (ret != sizeof(len)) {
61
+ "queue size too big, drop packet");
50
goto err;
62
+ packet_destroy(pkt, NULL);
51
}
63
+ pkt = NULL;
52
64
+ }
53
- ret = qemu_chr_fe_write_all(out, (uint8_t *)buf, size);
65
+
54
+ ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)buf, size);
66
*con = conn;
55
if (ret != size) {
67
56
goto err;
68
return 0;
57
}
69
diff --git a/net/trace-events b/net/trace-events
58
@@ -XXX,XX +XXX,XX @@ static void compare_pri_rs_finalize(SocketReadState *pri_rs)
70
index XXXXXXX..XXXXXXX 100644
59
71
--- a/net/trace-events
60
if (packet_enqueue(s, PRIMARY_IN)) {
72
+++ b/net/trace-events
61
trace_colo_compare_main("primary: unsupported packet in");
73
@@ -XXX,XX +XXX,XX @@ colo_proxy_main(const char *chr) ": %s"
62
- compare_chr_send(&s->chr_out, pri_rs->buf, pri_rs->packet_len);
74
63
+ compare_chr_send(s, pri_rs->buf, pri_rs->packet_len);
75
# colo-compare.c
64
} else {
76
colo_compare_main(const char *chr) ": %s"
65
/* compare connection */
77
+colo_compare_drop_packet(const char *queue, const char *chr) ": %s: %s"
66
g_queue_foreach(&s->conn_list, colo_compare_connection, s);
78
colo_compare_udp_miscompare(const char *sta, int size) ": %s = %d"
67
@@ -XXX,XX +XXX,XX @@ static void colo_flush_packets(void *opaque, void *user_data)
79
colo_compare_icmp_miscompare(const char *sta, int size) ": %s = %d"
68
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"
69
while (!g_queue_is_empty(&conn->primary_list)) {
70
pkt = g_queue_pop_head(&conn->primary_list);
71
- compare_chr_send(&s->chr_out, pkt->data, pkt->size);
72
+ compare_chr_send(s, pkt->data, pkt->size);
73
packet_destroy(pkt, NULL);
74
}
75
while (!g_queue_is_empty(&conn->secondary_list)) {
76
--
81
--
77
2.7.4
82
2.5.0
78
83
79
84
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
3
libFuzzer found using 'qemu-system-i386 -M q35':
4
5
qemu: hardware error: e1000e: PSRCTL.BSIZE0 cannot be zero
6
CPU #0:
7
EAX=00000000 EBX=00000000 ECX=00000000 EDX=00000663
8
ESI=00000000 EDI=00000000 EBP=00000000 ESP=00000000
9
EIP=0000fff0 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
10
ES =0000 00000000 0000ffff 00009300
11
CS =f000 ffff0000 0000ffff 00009b00
12
SS =0000 00000000 0000ffff 00009300
13
DS =0000 00000000 0000ffff 00009300
14
FS =0000 00000000 0000ffff 00009300
15
GS =0000 00000000 0000ffff 00009300
16
LDT=0000 00000000 0000ffff 00008200
17
TR =0000 00000000 0000ffff 00008b00
18
GDT= 00000000 0000ffff
19
IDT= 00000000 0000ffff
20
CR0=60000010 CR2=00000000 CR3=00000000 CR4=00000000
21
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
22
DR6=ffff0ff0 DR7=00000400
23
EFER=0000000000000000
24
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
25
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
26
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
27
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
28
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
29
XMM00=00000000000000000000000000000000 XMM01=00000000000000000000000000000000
30
XMM02=00000000000000000000000000000000 XMM03=00000000000000000000000000000000
31
XMM04=00000000000000000000000000000000 XMM05=00000000000000000000000000000000
32
XMM06=00000000000000000000000000000000 XMM07=00000000000000000000000000000000
33
==1988== ERROR: libFuzzer: deadly signal
34
#6 0x7fae4d3ea894 in __GI_abort (/lib64/libc.so.6+0x22894)
35
#7 0x563f4cc59a1d in hw_error (qemu-fuzz-i386+0xe8ca1d)
36
#8 0x563f4d7c93f2 in e1000e_set_psrctl (qemu-fuzz-i386+0x19fc3f2)
37
#9 0x563f4d7b798f in e1000e_core_write (qemu-fuzz-i386+0x19ea98f)
38
#10 0x563f4d7afc46 in e1000e_mmio_write (qemu-fuzz-i386+0x19e2c46)
39
#11 0x563f4cc9a0a7 in memory_region_write_accessor (qemu-fuzz-i386+0xecd0a7)
40
#12 0x563f4cc99c13 in access_with_adjusted_size (qemu-fuzz-i386+0xeccc13)
41
#13 0x563f4cc987b4 in memory_region_dispatch_write (qemu-fuzz-i386+0xecb7b4)
42
43
It simply sent the following 2 I/O command to the e1000e
44
PCI BAR #2 I/O region:
45
46
writew 0x0100 0x0c00 # RCTL = E1000_RCTL_DTYP_MASK
47
writeb 0x2170 0x00 # PSRCTL = 0
48
49
2813 static void
50
2814 e1000e_set_psrctl(E1000ECore *core, int index, uint32_t val)
51
2815 {
52
2816 if (core->mac[RCTL] & E1000_RCTL_DTYP_MASK) {
53
2817
54
2818 if ((val & E1000_PSRCTL_BSIZE0_MASK) == 0) {
55
2819 hw_error("e1000e: PSRCTL.BSIZE0 cannot be zero");
56
2820 }
57
58
Instead of calling hw_error() which abort the process (it is
59
meant for CPU fatal error condition, not for device logging),
60
log the invalid request with qemu_log_mask(LOG_GUEST_ERROR)
61
and return, ignoring the request.
62
63
Cc: qemu-stable@nongnu.org
64
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Signed-off-by: Jason Wang <jasowang@redhat.com>
65
Signed-off-by: Jason Wang <jasowang@redhat.com>
5
---
66
---
6
docs/colo-proxy.txt | 26 ++++++++++++++++++++++++++
67
hw/net/e1000e_core.c | 10 +++++++---
7
1 file changed, 26 insertions(+)
68
1 file changed, 7 insertions(+), 3 deletions(-)
8
69
9
diff --git a/docs/colo-proxy.txt b/docs/colo-proxy.txt
70
diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
10
index XXXXXXX..XXXXXXX 100644
71
index XXXXXXX..XXXXXXX 100644
11
--- a/docs/colo-proxy.txt
72
--- a/hw/net/e1000e_core.c
12
+++ b/docs/colo-proxy.txt
73
+++ b/hw/net/e1000e_core.c
13
@@ -XXX,XX +XXX,XX @@ Secondary(ip:3.3.3.8):
74
@@ -XXX,XX +XXX,XX @@
14
-chardev socket,id=red1,host=3.3.3.3,port=9004
75
*/
15
-object filter-redirector,id=f1,netdev=hn0,queue=tx,indev=red0
76
16
-object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1
77
#include "qemu/osdep.h"
17
+-object filter-rewriter,id=f3,netdev=hn0,queue=all
78
+#include "qemu/log.h"
18
+
79
#include "net/net.h"
19
+If you want to use virtio-net-pci or other driver with vnet_header:
80
#include "net/tap.h"
20
+
81
-#include "hw/hw.h"
21
+Primary(ip:3.3.3.3):
82
#include "hw/pci/msi.h"
22
+-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown
83
#include "hw/pci/msix.h"
23
+-device e1000,id=e0,netdev=hn0,mac=52:a4:00:12:78:66
84
#include "sysemu/runstate.h"
24
+-chardev socket,id=mirror0,host=3.3.3.3,port=9003,server,nowait
85
@@ -XXX,XX +XXX,XX @@ e1000e_set_psrctl(E1000ECore *core, int index, uint32_t val)
25
+-chardev socket,id=compare1,host=3.3.3.3,port=9004,server,nowait
86
if (core->mac[RCTL] & E1000_RCTL_DTYP_MASK) {
26
+-chardev socket,id=compare0,host=3.3.3.3,port=9001,server,nowait
87
27
+-chardev socket,id=compare0-0,host=3.3.3.3,port=9001
88
if ((val & E1000_PSRCTL_BSIZE0_MASK) == 0) {
28
+-chardev socket,id=compare_out,host=3.3.3.3,port=9005,server,nowait
89
- hw_error("e1000e: PSRCTL.BSIZE0 cannot be zero");
29
+-chardev socket,id=compare_out0,host=3.3.3.3,port=9005
90
+ qemu_log_mask(LOG_GUEST_ERROR,
30
+-object filter-mirror,id=m0,netdev=hn0,queue=tx,outdev=mirror0,vnet_hdr_support
91
+ "e1000e: PSRCTL.BSIZE0 cannot be zero");
31
+-object filter-redirector,netdev=hn0,id=redire0,queue=rx,indev=compare_out,vnet_hdr_support
92
+ return;
32
+-object filter-redirector,netdev=hn0,id=redire1,queue=rx,outdev=compare0,vnet_hdr_support
93
}
33
+-object colo-compare,id=comp0,primary_in=compare0-0,secondary_in=compare1,outdev=compare_out0,vnet_hdr_support
94
34
+
95
if ((val & E1000_PSRCTL_BSIZE1_MASK) == 0) {
35
+Secondary(ip:3.3.3.8):
96
- hw_error("e1000e: PSRCTL.BSIZE1 cannot be zero");
36
+-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,down script=/etc/qemu-ifdown
97
+ qemu_log_mask(LOG_GUEST_ERROR,
37
+-device e1000,netdev=hn0,mac=52:a4:00:12:78:66
98
+ "e1000e: PSRCTL.BSIZE1 cannot be zero");
38
+-chardev socket,id=red0,host=3.3.3.3,port=9003
99
+ return;
39
+-chardev socket,id=red1,host=3.3.3.3,port=9004
100
}
40
+-object filter-redirector,id=f1,netdev=hn0,queue=tx,indev=red0,vnet_hdr_support
101
}
41
+-object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1,vnet_hdr_support
102
42
+-object filter-rewriter,id=f3,netdev=hn0,queue=all,vnet_hdr_support
43
44
Note:
45
a.COLO-proxy must work with COLO-frame and Block-replication.
46
--
103
--
47
2.7.4
104
2.5.0
48
105
49
106
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
Add vnet_hdr_len arguments in NetClientState
3
It's been deprecated since QEMU v3.1, so it's time to finally
4
that make other module get real vnet_hdr_len easily.
4
remove it. The "id" parameter can simply be used instead.
5
5
6
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Signed-off-by: Thomas Huth <thuth@redhat.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
9
---
9
include/net/net.h | 1 +
10
docs/system/deprecated.rst | 15 +++++++++------
10
net/net.c | 1 +
11
net/net.c | 10 +---------
11
2 files changed, 2 insertions(+)
12
qapi/net.json | 3 ---
13
3 files changed, 10 insertions(+), 18 deletions(-)
12
14
13
diff --git a/include/net/net.h b/include/net/net.h
15
diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/include/net/net.h
17
--- a/docs/system/deprecated.rst
16
+++ b/include/net/net.h
18
+++ b/docs/system/deprecated.rst
17
@@ -XXX,XX +XXX,XX @@ struct NetClientState {
19
@@ -XXX,XX +XXX,XX @@ The 'file' driver for drives is no longer appropriate for character or host
18
unsigned int queue_index;
20
devices and will only accept regular files (S_IFREG). The correct driver
19
unsigned rxfilter_notify_enabled:1;
21
for these file types is 'host_cdrom' or 'host_device' as appropriate.
20
int vring_enable;
22
21
+ int vnet_hdr_len;
23
-``-net ...,name=``\ *name* (since 3.1)
22
QTAILQ_HEAD(NetFilterHead, NetFilterState) filters;
24
-''''''''''''''''''''''''''''''''''''''
23
};
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
------------------------------------
24
47
25
diff --git a/net/net.c b/net/net.c
48
diff --git a/net/net.c b/net/net.c
26
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
27
--- a/net/net.c
50
--- a/net/net.c
28
+++ b/net/net.c
51
+++ b/net/net.c
29
@@ -XXX,XX +XXX,XX @@ void qemu_set_vnet_hdr_len(NetClientState *nc, int len)
52
@@ -XXX,XX +XXX,XX @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp)
30
return;
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
}
31
}
80
}
32
81
33
+ nc->vnet_hdr_len = len;
82
- if (net_client_init_fun[netdev->type](netdev, name, peer, errp) < 0) {
34
nc->info->set_vnet_hdr_len(nc, len);
83
+ if (net_client_init_fun[netdev->type](netdev, netdev->id, peer, errp) < 0) {
35
}
84
/* FIXME drop when all init functions store an Error */
36
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
##
37
--
108
--
38
2.7.4
109
2.5.0
39
110
40
111
diff view generated by jsdifflib
New patch
1
1
From: Thomas Huth <thuth@redhat.com>
2
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