1
The following changes since commit 23895cbd82be95428e90168b12e925d0d3ca2f06:
1
The following changes since commit 6b99bb046dd36a6dd5525b8f88c2dcddae49222a:
2
2
3
Merge remote-tracking branch 'remotes/awilliam/tags/vfio-update-20201123.0' into staging (2020-11-23 18:51:13 +0000)
3
Merge tag 'pull-lu-20241122' of https://gitlab.com/rth7680/qemu into staging (2024-11-24 13:39:06 +0000)
4
4
5
are available in the git repository at:
5
are available in the Git repository at:
6
6
7
https://github.com/jasowang/qemu.git tags/net-pull-request
7
https://github.com/jasowang/qemu.git tags/net-pull-request
8
8
9
for you to fetch changes up to 9925990d01a92564af55f6f69d0f5f59b47609b1:
9
for you to fetch changes up to 7987d2be5a8bc3a502f89ba8cf3ac3e09f64d1ce:
10
10
11
net: Use correct default-path macro for downscript (2020-11-24 10:40:17 +0800)
11
virtio-net: Copy received header to buffer (2024-11-25 14:00:51 +0800)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
-----BEGIN PGP SIGNATURE-----
15
16
iQEzBAABCAAdFiEEIV1G9IJGaJ7HfzVi7wSWWzmNYhEFAmdEEtgACgkQ7wSWWzmN
17
YhH5qAgAlKdcx/gFt4EBXtjVq/qbPluEGOQxvcRYLlN90rPLHPgCjAoT5ly3fIv1
18
4kCgcVZyG8SdGu1n0TzTTS9kg5tL7weQ9xEWwF0oyyuZABgAB7w/wpC8MHSkJFOn
19
2Tv+2Iab0dJ+e1pw71OMpE/YR5X2xq5vopsSHRtnyGWfRPGswJFwka+f8FS5DSiq
20
2CeNxADgTkPxJgDmOrNSsAPz8Rns77FAZdvDMqFjx1Lrqm8kPv9jzwOMO+a/2LpC
21
t6OkpFzGjiiskPjSnSn/tzo4TfWYoABjJaI7b3vEqmNEJSTAaxltZNtSXZucctEt
22
1ihnFdjr/wPwGK/5Wu+qGnfDbFNxBw==
23
=W4y1
24
-----END PGP SIGNATURE-----
14
25
15
----------------------------------------------------------------
26
----------------------------------------------------------------
16
Keqian Zhu (1):
27
Akihiko Odaki (6):
17
net: Use correct default-path macro for downscript
28
net: checksum: Convert data to void *
29
virtio-net: Fix size check in dhclient workaround
30
virtio-net: Do not check for the queue before RSS
31
virtio-net: Fix hash reporting when the queue changes
32
virtio-net: Initialize hash reporting values
33
virtio-net: Copy received header to buffer
18
34
19
Paolo Bonzini (1):
35
hw/net/virtio-net.c | 108 +++++++++++++++++++++++++++----------------------
20
net: do not exit on "netdev_add help" monitor command
36
include/net/checksum.h | 2 +-
21
37
net/checksum.c | 4 +-
22
Prasad J Pandit (1):
38
3 files changed, 63 insertions(+), 51 deletions(-)
23
hw/net/e1000e: advance desc_offset in case of null descriptor
24
25
Yuri Benditovich (1):
26
net: purge queued rx packets on queue deletion
27
28
yuanjungong (1):
29
tap: fix a memory leak
30
31
hw/net/e1000e_core.c | 8 +++---
32
include/net/net.h | 1 +
33
monitor/hmp-cmds.c | 6 ++++
34
net/net.c | 80 +++++++++++++++++++++++++++-------------------------
35
net/tap.c | 5 +++-
36
5 files changed, 57 insertions(+), 43 deletions(-)
37
38
diff view generated by jsdifflib
1
From: Keqian Zhu <zhukeqian1@huawei.com>
1
From: Akihiko Odaki <akihiko.odaki@daynix.com>
2
2
3
Fixes: 63c4db4c2e6d (net: relocate paths to helpers and scripts)
3
Convert the data parameter of net_checksum_calculate() to void * to
4
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
4
save unnecessary casts for callers.
5
6
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
6
---
9
---
7
net/tap.c | 3 ++-
10
include/net/checksum.h | 2 +-
8
1 file changed, 2 insertions(+), 1 deletion(-)
11
net/checksum.c | 4 ++--
12
2 files changed, 3 insertions(+), 3 deletions(-)
9
13
10
diff --git a/net/tap.c b/net/tap.c
14
diff --git a/include/net/checksum.h b/include/net/checksum.h
11
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
12
--- a/net/tap.c
16
--- a/include/net/checksum.h
13
+++ b/net/tap.c
17
+++ b/include/net/checksum.h
14
@@ -XXX,XX +XXX,XX @@ free_fail:
18
@@ -XXX,XX +XXX,XX @@ uint32_t net_checksum_add_cont(int len, uint8_t *buf, int seq);
15
script = default_script = get_relocated_path(DEFAULT_NETWORK_SCRIPT);
19
uint16_t net_checksum_finish(uint32_t sum);
16
}
20
uint16_t net_checksum_tcpudp(uint16_t length, uint16_t proto,
17
if (!downscript) {
21
uint8_t *addrs, uint8_t *buf);
18
- downscript = default_downscript = get_relocated_path(DEFAULT_NETWORK_SCRIPT);
22
-void net_checksum_calculate(uint8_t *data, int length, int csum_flag);
19
+ downscript = default_downscript =
23
+void net_checksum_calculate(void *data, int length, int csum_flag);
20
+ get_relocated_path(DEFAULT_NETWORK_DOWN_SCRIPT);
24
21
}
25
static inline uint32_t
22
26
net_checksum_add(int len, uint8_t *buf)
23
if (tap->has_ifname) {
27
diff --git a/net/checksum.c b/net/checksum.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/net/checksum.c
30
+++ b/net/checksum.c
31
@@ -XXX,XX +XXX,XX @@ uint16_t net_checksum_tcpudp(uint16_t length, uint16_t proto,
32
return net_checksum_finish(sum);
33
}
34
35
-void net_checksum_calculate(uint8_t *data, int length, int csum_flag)
36
+void net_checksum_calculate(void *data, int length, int csum_flag)
37
{
38
int mac_hdr_len, ip_len;
39
struct ip_header *ip;
40
@@ -XXX,XX +XXX,XX @@ void net_checksum_calculate(uint8_t *data, int length, int csum_flag)
41
return;
42
}
43
44
- ip = (struct ip_header *)(data + mac_hdr_len);
45
+ ip = (struct ip_header *)((uint8_t *)data + mac_hdr_len);
46
47
if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {
48
return; /* not IPv4 */
24
--
49
--
25
2.7.4
50
2.42.0
26
51
27
52
diff view generated by jsdifflib
New patch
1
From: Akihiko Odaki <akihiko.odaki@daynix.com>
1
2
3
work_around_broken_dhclient() accesses IP and UDP headers to detect
4
relevant packets and to calculate checksums, but it didn't check if
5
the packet has size sufficient to accommodate them, causing out-of-bound
6
access hazards. Fix this by correcting the size requirement.
7
8
Fixes: 1d41b0c1ec66 ("Work around dhclient brokenness")
9
Cc: qemu-stable@nongnu.org
10
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
13
hw/net/virtio-net.c | 5 ++++-
14
1 file changed, 4 insertions(+), 1 deletion(-)
15
16
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/net/virtio-net.c
19
+++ b/hw/net/virtio-net.c
20
@@ -XXX,XX +XXX,XX @@ static void virtio_net_hdr_swap(VirtIODevice *vdev, struct virtio_net_hdr *hdr)
21
static void work_around_broken_dhclient(struct virtio_net_hdr *hdr,
22
uint8_t *buf, size_t size)
23
{
24
+ size_t csum_size = ETH_HLEN + sizeof(struct ip_header) +
25
+ sizeof(struct udp_header);
26
+
27
if ((hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && /* missing csum */
28
- (size > 27 && size < 1500) && /* normal sized MTU */
29
+ (size >= csum_size && size < 1500) && /* normal sized MTU */
30
(buf[12] == 0x08 && buf[13] == 0x00) && /* ethertype == IPv4 */
31
(buf[23] == 17) && /* ip.protocol == UDP */
32
(buf[34] == 0 && buf[35] == 67)) { /* udp.srcport == bootps */
33
--
34
2.42.0
diff view generated by jsdifflib
1
From: Prasad J Pandit <pjp@fedoraproject.org>
1
From: Akihiko Odaki <akihiko.odaki@daynix.com>
2
2
3
While receiving packets via e1000e_write_packet_to_guest() routine,
3
virtio_net_can_receive() checks if the queue is ready, but RSS will
4
'desc_offset' is advanced only when RX descriptor is processed. And
4
change the queue to use so, strictly speaking, we may still be able to
5
RX descriptor is not processed if it has NULL buffer address.
5
receive the packet even if the queue initially provided is not ready.
6
This may lead to an infinite loop condition. Increament 'desc_offset'
6
Perform RSS before virtio_net_can_receive() to cover such a case.
7
to process next descriptor in the ring to avoid infinite loop.
8
7
9
Reported-by: Cheol-woo Myung <330cjfdn@gmail.com>
8
Fixes: 4474e37a5b3a ("virtio-net: implement RX RSS processing")
10
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
9
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
11
---
13
hw/net/e1000e_core.c | 8 ++++----
12
hw/net/virtio-net.c | 8 ++++----
14
1 file changed, 4 insertions(+), 4 deletions(-)
13
1 file changed, 4 insertions(+), 4 deletions(-)
15
14
16
diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
15
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/net/e1000e_core.c
17
--- a/hw/net/virtio-net.c
19
+++ b/hw/net/e1000e_core.c
18
+++ b/hw/net/virtio-net.c
20
@@ -XXX,XX +XXX,XX @@ e1000e_write_packet_to_guest(E1000ECore *core, struct NetRxPkt *pkt,
19
@@ -XXX,XX +XXX,XX @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
21
(const char *) &fcs_pad, e1000x_fcs_len(core->mac));
20
size_t offset, i, guest_offset, j;
22
}
21
ssize_t err;
23
}
22
24
- desc_offset += desc_size;
23
- if (!virtio_net_can_receive(nc)) {
25
- if (desc_offset >= total_size) {
24
- return -1;
26
- is_last = true;
25
- }
27
- }
26
-
28
} else { /* as per intel docs; skip descriptors with null buf addr */
27
if (!no_rss && n->rss_data.enabled && n->rss_data.enabled_software_rss) {
29
trace_e1000e_rx_null_descriptor();
28
int index = virtio_net_process_rss(nc, buf, size, &extra_hdr);
29
if (index >= 0) {
30
@@ -XXX,XX +XXX,XX @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
30
}
31
}
31
+ desc_offset += desc_size;
32
}
32
+ if (desc_offset >= total_size) {
33
33
+ is_last = true;
34
+ if (!virtio_net_can_receive(nc)) {
34
+ }
35
+ return -1;
35
36
+ }
36
e1000e_write_rx_descr(core, desc, is_last ? core->rx_pkt : NULL,
37
+
37
rss_info, do_ps ? ps_hdr_len : 0, &bastate.written);
38
/* hdr_len refers to the header we supply to the guest */
39
if (!virtio_net_has_buffers(q, size + n->guest_hdr_len - n->host_hdr_len)) {
40
return 0;
38
--
41
--
39
2.7.4
42
2.42.0
40
41
diff view generated by jsdifflib
1
From: Yuri Benditovich <yuri.benditovich@daynix.com>
1
From: Akihiko Odaki <akihiko.odaki@daynix.com>
2
2
3
https://bugzilla.redhat.com/show_bug.cgi?id=1829272
3
virtio_net_process_rss() fills the values used for hash reporting, but
4
When deleting queue pair, purge pending RX packets if any.
4
the values used to be thrown away with a recursive function call if
5
Example of problematic flow:
5
the queue changes after RSS. Avoid the function call to keep the values.
6
1. Bring up q35 VM with tap (vhost off) and virtio-net or e1000e
7
2. Run ping flood to the VM NIC ( 1 ms interval)
8
3. Hot unplug the NIC device (device_del)
9
During unplug process one or more packets come, the NIC
10
can't receive, tap disables read_poll
11
4. Hot plug the device (device_add) with the same netdev
12
The tap stays with read_poll disabled and does not receive
13
any packets anymore (tap_send never triggered)
14
6
15
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
7
Fixes: a4c960eedcd2 ("virtio-net: Do not write hashes to peer buffer")
8
Buglink: https://issues.redhat.com/browse/RHEL-59572
9
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
16
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
17
---
11
---
18
net/net.c | 12 ++++++++----
12
hw/net/virtio-net.c | 14 +++++++-------
19
1 file changed, 8 insertions(+), 4 deletions(-)
13
1 file changed, 7 insertions(+), 7 deletions(-)
20
14
21
diff --git a/net/net.c b/net/net.c
15
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
22
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
23
--- a/net/net.c
17
--- a/hw/net/virtio-net.c
24
+++ b/net/net.c
18
+++ b/hw/net/virtio-net.c
25
@@ -XXX,XX +XXX,XX @@ void qemu_del_nic(NICState *nic)
19
@@ -XXX,XX +XXX,XX @@ static int virtio_net_process_rss(NetClientState *nc, const uint8_t *buf,
26
20
}
27
qemu_macaddr_set_free(&nic->conf->macaddr);
21
28
22
static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
29
- /* If this is a peer NIC and peer has already been deleted, free it now. */
23
- size_t size, bool no_rss)
30
- if (nic->peer_deleted) {
24
+ size_t size)
31
- for (i = 0; i < queues; i++) {
25
{
32
- qemu_free_net_client(qemu_get_subqueue(nic, i)->peer);
26
VirtIONet *n = qemu_get_nic_opaque(nc);
33
+ for (i = 0; i < queues; i++) {
27
- VirtIONetQueue *q = virtio_net_get_subqueue(nc);
34
+ NetClientState *nc = qemu_get_subqueue(nic, i);
28
+ VirtIONetQueue *q;
35
+ /* If this is a peer NIC and peer has already been deleted, free it now. */
29
VirtIODevice *vdev = VIRTIO_DEVICE(n);
36
+ if (nic->peer_deleted) {
30
VirtQueueElement *elems[VIRTQUEUE_MAX_SIZE];
37
+ qemu_free_net_client(nc->peer);
31
size_t lens[VIRTQUEUE_MAX_SIZE];
38
+ } else if (nc->peer) {
32
@@ -XXX,XX +XXX,XX @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
39
+ /* if there are RX packets pending, complete them */
33
size_t offset, i, guest_offset, j;
40
+ qemu_purge_queued_packets(nc->peer);
34
ssize_t err;
35
36
- if (!no_rss && n->rss_data.enabled && n->rss_data.enabled_software_rss) {
37
+ if (n->rss_data.enabled && n->rss_data.enabled_software_rss) {
38
int index = virtio_net_process_rss(nc, buf, size, &extra_hdr);
39
if (index >= 0) {
40
- NetClientState *nc2 =
41
- qemu_get_subqueue(n->nic, index % n->curr_queue_pairs);
42
- return virtio_net_receive_rcu(nc2, buf, size, true);
43
+ nc = qemu_get_subqueue(n->nic, index % n->curr_queue_pairs);
41
}
44
}
42
}
45
}
43
46
47
@@ -XXX,XX +XXX,XX @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
48
return -1;
49
}
50
51
+ q = virtio_net_get_subqueue(nc);
52
+
53
/* hdr_len refers to the header we supply to the guest */
54
if (!virtio_net_has_buffers(q, size + n->guest_hdr_len - n->host_hdr_len)) {
55
return 0;
56
@@ -XXX,XX +XXX,XX @@ static ssize_t virtio_net_do_receive(NetClientState *nc, const uint8_t *buf,
57
{
58
RCU_READ_LOCK_GUARD();
59
60
- return virtio_net_receive_rcu(nc, buf, size, false);
61
+ return virtio_net_receive_rcu(nc, buf, size);
62
}
63
64
/*
44
--
65
--
45
2.7.4
66
2.42.0
46
47
diff view generated by jsdifflib
1
From: yuanjungong <ruc_gongyuanjun@163.com>
1
From: Akihiko Odaki <akihiko.odaki@daynix.com>
2
2
3
Close fd before returning.
3
The specification says hash_report should be set to
4
VIRTIO_NET_HASH_REPORT_NONE if VIRTIO_NET_F_HASH_REPORT is negotiated
5
but not configured with VIRTIO_NET_CTRL_MQ_RSS_CONFIG. However,
6
virtio_net_receive_rcu() instead wrote out the content of the extra_hdr
7
variable, which is not uninitialized in such a case.
4
8
5
Buglink: https://bugs.launchpad.net/qemu/+bug/1904486
9
Fix this by zeroing the extra_hdr.
6
10
7
Signed-off-by: yuanjungong <ruc_gongyuanjun@163.com>
11
Fixes: e22f0603fb2f ("virtio-net: reference implementation of hash report")
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
14
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
15
---
11
net/tap.c | 2 ++
16
hw/net/virtio-net.c | 2 ++
12
1 file changed, 2 insertions(+)
17
1 file changed, 2 insertions(+)
13
18
14
diff --git a/net/tap.c b/net/tap.c
19
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
15
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
16
--- a/net/tap.c
21
--- a/hw/net/virtio-net.c
17
+++ b/net/tap.c
22
+++ b/hw/net/virtio-net.c
18
@@ -XXX,XX +XXX,XX @@ int net_init_tap(const Netdev *netdev, const char *name,
23
@@ -XXX,XX +XXX,XX @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
19
if (ret < 0) {
24
size_t offset, i, guest_offset, j;
20
error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d",
25
ssize_t err;
21
name, fd);
26
22
+ close(fd);
27
+ memset(&extra_hdr, 0, sizeof(extra_hdr));
23
return -1;
28
+
24
}
29
if (n->rss_data.enabled && n->rss_data.enabled_software_rss) {
25
30
int index = virtio_net_process_rss(nc, buf, size, &extra_hdr);
26
@@ -XXX,XX +XXX,XX @@ int net_init_tap(const Netdev *netdev, const char *name,
31
if (index >= 0) {
27
vhostfdname, vnet_hdr, fd, &err);
28
if (err) {
29
error_propagate(errp, err);
30
+ close(fd);
31
return -1;
32
}
33
} else if (tap->has_fds) {
34
--
32
--
35
2.7.4
33
2.42.0
36
34
37
35
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
From: Akihiko Odaki <akihiko.odaki@daynix.com>
2
2
3
"netdev_add help" is causing QEMU to exit because the code that
3
receive_header() used to cast the const qualifier of the pointer to the
4
invokes show_netdevs is shared between CLI and HMP processing.
4
received packet away to modify the header. Avoid this by copying the
5
Move the check to the callers so that exit(0) remains only
5
received header to buffer.
6
in the CLI flow.
7
6
8
"netdev_add help" is not fixed by this patch; that is left for
7
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
9
later work.
10
11
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
---
9
---
14
include/net/net.h | 1 +
10
hw/net/virtio-net.c | 85 ++++++++++++++++++++++++---------------------
15
monitor/hmp-cmds.c | 6 +++++
11
1 file changed, 46 insertions(+), 39 deletions(-)
16
net/net.c | 68 +++++++++++++++++++++++++++---------------------------
17
3 files changed, 41 insertions(+), 34 deletions(-)
18
12
19
diff --git a/include/net/net.h b/include/net/net.h
13
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
20
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
21
--- a/include/net/net.h
15
--- a/hw/net/virtio-net.c
22
+++ b/include/net/net.h
16
+++ b/hw/net/virtio-net.c
23
@@ -XXX,XX +XXX,XX @@ extern const char *host_net_devices[];
17
@@ -XXX,XX +XXX,XX @@ static void virtio_net_hdr_swap(VirtIODevice *vdev, struct virtio_net_hdr *hdr)
24
18
* cache.
25
/* from net.c */
19
*/
26
int net_client_parse(QemuOptsList *opts_list, const char *str);
20
static void work_around_broken_dhclient(struct virtio_net_hdr *hdr,
27
+void show_netdevs(void);
21
- uint8_t *buf, size_t size)
28
int net_init_clients(Error **errp);
22
+ size_t *hdr_len, const uint8_t *buf,
29
void net_check_clients(void);
23
+ size_t buf_size, size_t *buf_offset)
30
void net_cleanup(void);
31
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/monitor/hmp-cmds.c
34
+++ b/monitor/hmp-cmds.c
35
@@ -XXX,XX +XXX,XX @@
36
#include "qemu/option.h"
37
#include "qemu/timer.h"
38
#include "qemu/sockets.h"
39
+#include "qemu/help_option.h"
40
#include "monitor/monitor-internal.h"
41
#include "qapi/error.h"
42
#include "qapi/clone-visitor.h"
43
@@ -XXX,XX +XXX,XX @@ void hmp_netdev_add(Monitor *mon, const QDict *qdict)
44
{
24
{
45
Error *err = NULL;
25
size_t csum_size = ETH_HLEN + sizeof(struct ip_header) +
46
QemuOpts *opts;
26
sizeof(struct udp_header);
47
+ const char *type = qdict_get_try_str(qdict, "type");
27
48
28
+ buf += *buf_offset;
49
+ if (type && is_help_option(type)) {
29
+ buf_size -= *buf_offset;
50
+ show_netdevs();
30
+
51
+ return;
31
if ((hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && /* missing csum */
52
+ }
32
- (size >= csum_size && size < 1500) && /* normal sized MTU */
53
opts = qemu_opts_from_qdict(qemu_find_opts("netdev"), qdict, &err);
33
+ (buf_size >= csum_size && buf_size < 1500) && /* normal sized MTU */
54
if (err) {
34
(buf[12] == 0x08 && buf[13] == 0x00) && /* ethertype == IPv4 */
55
goto out;
35
(buf[23] == 17) && /* ip.protocol == UDP */
56
diff --git a/net/net.c b/net/net.c
36
(buf[34] == 0 && buf[35] == 67)) { /* udp.srcport == bootps */
57
index XXXXXXX..XXXXXXX 100644
37
- net_checksum_calculate(buf, size, CSUM_UDP);
58
--- a/net/net.c
38
+ memcpy((uint8_t *)hdr + *hdr_len, buf, csum_size);
59
+++ b/net/net.c
39
+ net_checksum_calculate((uint8_t *)hdr + *hdr_len, csum_size, CSUM_UDP);
60
@@ -XXX,XX +XXX,XX @@
40
hdr->flags &= ~VIRTIO_NET_HDR_F_NEEDS_CSUM;
61
#include "qemu/config-file.h"
41
+ *hdr_len += csum_size;
62
#include "qemu/ctype.h"
42
+ *buf_offset += csum_size;
63
#include "qemu/iov.h"
64
+#include "qemu/qemu-print.h"
65
#include "qemu/main-loop.h"
66
#include "qemu/option.h"
67
#include "qapi/error.h"
68
@@ -XXX,XX +XXX,XX @@ static int net_client_init1(const Netdev *netdev, bool is_netdev, Error **errp)
69
return 0;
70
}
71
72
-static void show_netdevs(void)
73
+void show_netdevs(void)
74
{
75
int idx;
76
const char *available_netdevs[] = {
77
@@ -XXX,XX +XXX,XX @@ static void show_netdevs(void)
78
#endif
79
};
80
81
- printf("Available netdev backend types:\n");
82
+ qemu_printf("Available netdev backend types:\n");
83
for (idx = 0; idx < ARRAY_SIZE(available_netdevs); idx++) {
84
- puts(available_netdevs[idx]);
85
+ qemu_printf("%s\n", available_netdevs[idx]);
86
}
43
}
87
}
44
}
88
45
89
@@ -XXX,XX +XXX,XX @@ static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp)
46
-static void receive_header(VirtIONet *n, const struct iovec *iov, int iov_cnt,
90
int ret = -1;
47
- const void *buf, size_t size)
91
Visitor *v = opts_visitor_new(opts);
48
+static size_t receive_header(VirtIONet *n, struct virtio_net_hdr *hdr,
92
49
+ const void *buf, size_t buf_size,
93
- const char *type = qemu_opt_get(opts, "type");
50
+ size_t *buf_offset)
94
-
51
{
95
- if (is_netdev && type && is_help_option(type)) {
52
- if (n->has_vnet_hdr) {
96
- show_netdevs();
53
- /* FIXME this cast is evil */
97
- exit(0);
54
- void *wbuf = (void *)buf;
55
- work_around_broken_dhclient(wbuf, wbuf + n->host_hdr_len,
56
- size - n->host_hdr_len);
57
+ size_t hdr_len = n->guest_hdr_len;
58
59
- if (n->needs_vnet_hdr_swap) {
60
- virtio_net_hdr_swap(VIRTIO_DEVICE(n), wbuf);
61
- }
62
- iov_from_buf(iov, iov_cnt, 0, buf, sizeof(struct virtio_net_hdr));
98
- } else {
63
- } else {
99
- /* Parse convenience option format ip6-net=fec0::0[/64] */
64
- struct virtio_net_hdr hdr = {
100
- const char *ip6_net = qemu_opt_get(opts, "ipv6-net");
65
- .flags = 0,
101
+ /* Parse convenience option format ip6-net=fec0::0[/64] */
66
- .gso_type = VIRTIO_NET_HDR_GSO_NONE
102
+ const char *ip6_net = qemu_opt_get(opts, "ipv6-net");
67
- };
103
68
- iov_from_buf(iov, iov_cnt, 0, &hdr, sizeof hdr);
104
- if (ip6_net) {
69
+ memcpy(hdr, buf, sizeof(struct virtio_net_hdr));
105
- char *prefix_addr;
70
+
106
- unsigned long prefix_len = 64; /* Default 64bit prefix length. */
71
+ *buf_offset = n->host_hdr_len;
107
+ if (ip6_net) {
72
+ work_around_broken_dhclient(hdr, &hdr_len, buf, buf_size, buf_offset);
108
+ char *prefix_addr;
73
+
109
+ unsigned long prefix_len = 64; /* Default 64bit prefix length. */
74
+ if (n->needs_vnet_hdr_swap) {
110
75
+ virtio_net_hdr_swap(VIRTIO_DEVICE(n), hdr);
111
- substrings = g_strsplit(ip6_net, "/", 2);
76
}
112
- if (!substrings || !substrings[0]) {
77
+
113
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "ipv6-net",
78
+ return hdr_len;
114
- "a valid IPv6 prefix");
79
}
115
- goto out;
80
81
static int receive_filter(VirtIONet *n, const uint8_t *buf, int size)
82
@@ -XXX,XX +XXX,XX @@ static int virtio_net_process_rss(NetClientState *nc, const uint8_t *buf,
83
return (index == new_index) ? -1 : new_index;
84
}
85
86
+typedef struct Header {
87
+ struct virtio_net_hdr_v1_hash virtio_net;
88
+ struct eth_header eth;
89
+ struct ip_header ip;
90
+ struct udp_header udp;
91
+} Header;
92
+
93
static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
94
size_t size)
95
{
96
@@ -XXX,XX +XXX,XX @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
97
VirtQueueElement *elems[VIRTQUEUE_MAX_SIZE];
98
size_t lens[VIRTQUEUE_MAX_SIZE];
99
struct iovec mhdr_sg[VIRTQUEUE_MAX_SIZE];
100
- struct virtio_net_hdr_v1_hash extra_hdr;
101
+ Header hdr;
102
unsigned mhdr_cnt = 0;
103
size_t offset, i, guest_offset, j;
104
ssize_t err;
105
106
- memset(&extra_hdr, 0, sizeof(extra_hdr));
107
+ memset(&hdr.virtio_net, 0, sizeof(hdr.virtio_net));
108
109
if (n->rss_data.enabled && n->rss_data.enabled_software_rss) {
110
- int index = virtio_net_process_rss(nc, buf, size, &extra_hdr);
111
+ int index = virtio_net_process_rss(nc, buf, size, &hdr.virtio_net);
112
if (index >= 0) {
113
nc = qemu_get_subqueue(n->nic, index % n->curr_queue_pairs);
114
}
115
@@ -XXX,XX +XXX,XX @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
116
if (n->mergeable_rx_bufs) {
117
mhdr_cnt = iov_copy(mhdr_sg, ARRAY_SIZE(mhdr_sg),
118
sg, elem->in_num,
119
- offsetof(typeof(extra_hdr), hdr.num_buffers),
120
- sizeof(extra_hdr.hdr.num_buffers));
121
+ offsetof(typeof(hdr),
122
+ virtio_net.hdr.num_buffers),
123
+ sizeof(hdr.virtio_net.hdr.num_buffers));
124
}
125
126
- receive_header(n, sg, elem->in_num, buf, size);
127
- if (n->rss_data.populate_hash) {
128
- offset = offsetof(typeof(extra_hdr), hash_value);
129
- iov_from_buf(sg, elem->in_num, offset,
130
- (char *)&extra_hdr + offset,
131
- sizeof(extra_hdr.hash_value) +
132
- sizeof(extra_hdr.hash_report));
116
- }
133
- }
117
+ substrings = g_strsplit(ip6_net, "/", 2);
134
- offset = n->host_hdr_len;
118
+ if (!substrings || !substrings[0]) {
135
- total += n->guest_hdr_len;
119
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "ipv6-net",
136
- guest_offset = n->guest_hdr_len;
120
+ "a valid IPv6 prefix");
137
+ guest_offset = n->has_vnet_hdr ?
121
+ goto out;
138
+ receive_header(n, (struct virtio_net_hdr *)&hdr,
122
+ }
139
+ buf, size, &offset) :
123
140
+ n->guest_hdr_len;
124
- prefix_addr = substrings[0];
141
+
125
+ prefix_addr = substrings[0];
142
+ iov_from_buf(sg, elem->in_num, 0, &hdr, guest_offset);
126
143
+ total += guest_offset;
127
- /* Handle user-specified prefix length. */
144
} else {
128
- if (substrings[1] &&
145
guest_offset = 0;
129
- qemu_strtoul(substrings[1], NULL, 10, &prefix_len))
130
- {
131
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
132
- "ipv6-prefixlen", "a number");
133
- goto out;
134
- }
135
-
136
- qemu_opt_set(opts, "ipv6-prefix", prefix_addr, &error_abort);
137
- qemu_opt_set_number(opts, "ipv6-prefixlen", prefix_len,
138
- &error_abort);
139
- qemu_opt_unset(opts, "ipv6-net");
140
+ /* Handle user-specified prefix length. */
141
+ if (substrings[1] &&
142
+ qemu_strtoul(substrings[1], NULL, 10, &prefix_len))
143
+ {
144
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
145
+ "ipv6-prefixlen", "a number");
146
+ goto out;
147
}
146
}
148
+
147
@@ -XXX,XX +XXX,XX @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
149
+ qemu_opt_set(opts, "ipv6-prefix", prefix_addr, &error_abort);
150
+ qemu_opt_set_number(opts, "ipv6-prefixlen", prefix_len,
151
+ &error_abort);
152
+ qemu_opt_unset(opts, "ipv6-net");
153
}
148
}
154
149
155
/* Create an ID for -net if the user did not specify one */
150
if (mhdr_cnt) {
156
@@ -XXX,XX +XXX,XX @@ static int net_init_client(void *dummy, QemuOpts *opts, Error **errp)
151
- virtio_stw_p(vdev, &extra_hdr.hdr.num_buffers, i);
157
152
+ virtio_stw_p(vdev, &hdr.virtio_net.hdr.num_buffers, i);
158
static int net_init_netdev(void *dummy, QemuOpts *opts, Error **errp)
153
iov_from_buf(mhdr_sg, mhdr_cnt,
159
{
154
0,
160
+ const char *type = qemu_opt_get(opts, "type");
155
- &extra_hdr.hdr.num_buffers,
161
+
156
- sizeof extra_hdr.hdr.num_buffers);
162
+ if (type && is_help_option(type)) {
157
+ &hdr.virtio_net.hdr.num_buffers,
163
+ show_netdevs();
158
+ sizeof hdr.virtio_net.hdr.num_buffers);
164
+ exit(0);
159
}
165
+ }
160
166
return net_client_init(opts, true, errp);
161
for (j = 0; j < i; j++) {
167
}
168
169
--
162
--
170
2.7.4
163
2.42.0
171
172
diff view generated by jsdifflib