1 | The following changes since commit 23895cbd82be95428e90168b12e925d0d3ca2f06: | 1 | The following changes since commit e81eb5e6d108008445821e4f891fb9563016c71b: |
---|---|---|---|
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 remote-tracking branch 'remotes/bonzini-gitlab/tags/for-upstream' into staging (2021-01-23 22:34:21 +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 f574633529926697ced51b6865e5c50bbb78bf1b: |
10 | 10 | ||
11 | net: Use correct default-path macro for downscript (2020-11-24 10:40:17 +0800) | 11 | net: checksum: Introduce fine control over checksum type (2021-01-25 17:04:56 +0800) |
12 | 12 | ||
13 | ---------------------------------------------------------------- | 13 | ---------------------------------------------------------------- |
14 | 14 | ||
15 | ---------------------------------------------------------------- | 15 | ---------------------------------------------------------------- |
16 | Keqian Zhu (1): | 16 | Bin Meng (1): |
17 | net: Use correct default-path macro for downscript | 17 | net: checksum: Introduce fine control over checksum type |
18 | 18 | ||
19 | Paolo Bonzini (1): | 19 | Guishan Qin (1): |
20 | net: do not exit on "netdev_add help" monitor command | 20 | net: checksum: Add IP header checksum calculation |
21 | 21 | ||
22 | Prasad J Pandit (1): | 22 | Markus Armbruster (1): |
23 | hw/net/e1000e: advance desc_offset in case of null descriptor | 23 | net: Fix handling of id in netdev_add and netdev_del |
24 | 24 | ||
25 | Yuri Benditovich (1): | 25 | Markus Carlstedt (1): |
26 | net: purge queued rx packets on queue deletion | 26 | net: checksum: Skip fragmented IP packets |
27 | 27 | ||
28 | yuanjungong (1): | 28 | hw/net/allwinner-sun8i-emac.c | 2 +- |
29 | tap: fix a memory leak | 29 | hw/net/cadence_gem.c | 2 +- |
30 | 30 | hw/net/fsl_etsec/rings.c | 18 +++++++++--------- | |
31 | hw/net/e1000e_core.c | 8 +++--- | 31 | hw/net/ftgmac100.c | 13 ++++++++++++- |
32 | include/net/net.h | 1 + | 32 | hw/net/imx_fec.c | 20 ++++++++------------ |
33 | monitor/hmp-cmds.c | 6 ++++ | 33 | hw/net/virtio-net.c | 2 +- |
34 | net/net.c | 80 +++++++++++++++++++++++++++------------------------- | 34 | hw/net/xen_nic.c | 2 +- |
35 | net/tap.c | 5 +++- | 35 | include/net/checksum.h | 7 ++++++- |
36 | 5 files changed, 57 insertions(+), 43 deletions(-) | 36 | net/checksum.c | 24 +++++++++++++++++++++--- |
37 | net/filter-rewriter.c | 4 ++-- | ||
38 | net/net.c | 20 ++++++++++++++++++-- | ||
39 | 11 files changed, 80 insertions(+), 34 deletions(-) | ||
37 | 40 | ||
38 | 41 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Prasad J Pandit <pjp@fedoraproject.org> | ||
2 | 1 | ||
3 | While receiving packets via e1000e_write_packet_to_guest() routine, | ||
4 | 'desc_offset' is advanced only when RX descriptor is processed. And | ||
5 | RX descriptor is not processed if it has NULL buffer address. | ||
6 | This may lead to an infinite loop condition. Increament 'desc_offset' | ||
7 | to process next descriptor in the ring to avoid infinite loop. | ||
8 | |||
9 | Reported-by: Cheol-woo Myung <330cjfdn@gmail.com> | ||
10 | Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org> | ||
11 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
12 | --- | ||
13 | hw/net/e1000e_core.c | 8 ++++---- | ||
14 | 1 file changed, 4 insertions(+), 4 deletions(-) | ||
15 | |||
16 | diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c | ||
17 | index XXXXXXX..XXXXXXX 100644 | ||
18 | --- a/hw/net/e1000e_core.c | ||
19 | +++ b/hw/net/e1000e_core.c | ||
20 | @@ -XXX,XX +XXX,XX @@ e1000e_write_packet_to_guest(E1000ECore *core, struct NetRxPkt *pkt, | ||
21 | (const char *) &fcs_pad, e1000x_fcs_len(core->mac)); | ||
22 | } | ||
23 | } | ||
24 | - desc_offset += desc_size; | ||
25 | - if (desc_offset >= total_size) { | ||
26 | - is_last = true; | ||
27 | - } | ||
28 | } else { /* as per intel docs; skip descriptors with null buf addr */ | ||
29 | trace_e1000e_rx_null_descriptor(); | ||
30 | } | ||
31 | + desc_offset += desc_size; | ||
32 | + if (desc_offset >= total_size) { | ||
33 | + is_last = true; | ||
34 | + } | ||
35 | |||
36 | e1000e_write_rx_descr(core, desc, is_last ? core->rx_pkt : NULL, | ||
37 | rss_info, do_ps ? ps_hdr_len : 0, &bastate.written); | ||
38 | -- | ||
39 | 2.7.4 | ||
40 | |||
41 | diff view generated by jsdifflib |
1 | From: Yuri Benditovich <yuri.benditovich@daynix.com> | 1 | From: Markus Armbruster <armbru@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | https://bugzilla.redhat.com/show_bug.cgi?id=1829272 | 3 | CLI -netdev accumulates in option group "netdev". |
4 | When deleting queue pair, purge pending RX packets if any. | ||
5 | Example of problematic flow: | ||
6 | 1. Bring up q35 VM with tap (vhost off) and virtio-net or e1000e | ||
7 | 2. Run ping flood to the VM NIC ( 1 ms interval) | ||
8 | 3. Hot unplug the NIC device (device_del) | ||
9 | During unplug process one or more packets come, the NIC | ||
10 | can't receive, tap disables read_poll | ||
11 | 4. Hot plug the device (device_add) with the same netdev | ||
12 | The tap stays with read_poll disabled and does not receive | ||
13 | any packets anymore (tap_send never triggered) | ||
14 | 4 | ||
15 | Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com> | 5 | Before commit 08712fcb85 "net: Track netdevs in NetClientState rather |
6 | than QemuOpt", netdev_add added to the option group, and netdev_del | ||
7 | removed from it, both HMP and QMP. Thus, every netdev had a | ||
8 | corresponding QemuOpts in this option group. | ||
9 | |||
10 | Commit 08712fcb85 dropped this for QMP netdev_add and both netdev_del. | ||
11 | Now a netdev has a corresponding QemuOpts only when it was created | ||
12 | with CLI or HMP. Two issues: | ||
13 | |||
14 | * QMP and HMP netdev_del can leave QemuOpts behind, breaking HMP | ||
15 | netdev_add. Reproducer: | ||
16 | |||
17 | $ qemu-system-x86_64 -S -display none -nodefaults -monitor stdio | ||
18 | QEMU 5.1.92 monitor - type 'help' for more information | ||
19 | (qemu) netdev_add user,id=net0 | ||
20 | (qemu) info network | ||
21 | net0: index=0,type=user,net=10.0.2.0,restrict=off | ||
22 | (qemu) netdev_del net0 | ||
23 | (qemu) info network | ||
24 | (qemu) netdev_add user,id=net0 | ||
25 | upstream-qemu: Duplicate ID 'net0' for netdev | ||
26 | Try "help netdev_add" for more information | ||
27 | |||
28 | Fix by restoring the QemuOpts deletion in qmp_netdev_del(), but with | ||
29 | a guard, because the QemuOpts need not exist. | ||
30 | |||
31 | * QMP netdev_add loses its "no duplicate ID" check. Reproducer: | ||
32 | |||
33 | $ qemu-system-x86_64 -S -display none -qmp stdio | ||
34 | {"QMP": {"version": {"qemu": {"micro": 92, "minor": 1, "major": 5}, "package": "v5.2.0-rc2-1-g02c1f0142c"}, "capabilities": ["oob"]}} | ||
35 | {"execute": "qmp_capabilities"} | ||
36 | {"return": {}} | ||
37 | {"execute": "netdev_add", "arguments": {"type": "user", "id":"net0"}} | ||
38 | {"return": {}} | ||
39 | {"execute": "netdev_add", "arguments": {"type": "user", "id":"net0"}} | ||
40 | {"return": {}} | ||
41 | |||
42 | Fix by adding a duplicate ID check to net_client_init1() to replace | ||
43 | the lost one. The check is redundant for callers where QemuOpts | ||
44 | still checks, i.e. for CLI and HMP. | ||
45 | |||
46 | Reported-by: Andrew Melnichenko <andrew@daynix.com> | ||
47 | Fixes: 08712fcb851034228b61f75bd922863a984a4f60 | ||
48 | Cc: qemu-stable@nongnu.org | ||
49 | Signed-off-by: Markus Armbruster <armbru@redhat.com> | ||
50 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
16 | Signed-off-by: Jason Wang <jasowang@redhat.com> | 51 | Signed-off-by: Jason Wang <jasowang@redhat.com> |
17 | --- | 52 | --- |
18 | net/net.c | 12 ++++++++---- | 53 | net/net.c | 20 ++++++++++++++++++-- |
19 | 1 file changed, 8 insertions(+), 4 deletions(-) | 54 | 1 file changed, 18 insertions(+), 2 deletions(-) |
20 | 55 | ||
21 | diff --git a/net/net.c b/net/net.c | 56 | diff --git a/net/net.c b/net/net.c |
22 | index XXXXXXX..XXXXXXX 100644 | 57 | index XXXXXXX..XXXXXXX 100644 |
23 | --- a/net/net.c | 58 | --- a/net/net.c |
24 | +++ b/net/net.c | 59 | +++ b/net/net.c |
25 | @@ -XXX,XX +XXX,XX @@ void qemu_del_nic(NICState *nic) | 60 | @@ -XXX,XX +XXX,XX @@ static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])( |
26 | 61 | static int net_client_init1(const Netdev *netdev, bool is_netdev, Error **errp) | |
27 | qemu_macaddr_set_free(&nic->conf->macaddr); | 62 | { |
28 | 63 | NetClientState *peer = NULL; | |
29 | - /* If this is a peer NIC and peer has already been deleted, free it now. */ | 64 | + NetClientState *nc; |
30 | - if (nic->peer_deleted) { | 65 | |
31 | - for (i = 0; i < queues; i++) { | 66 | if (is_netdev) { |
32 | - qemu_free_net_client(qemu_get_subqueue(nic, i)->peer); | 67 | if (netdev->type == NET_CLIENT_DRIVER_NIC || |
33 | + for (i = 0; i < queues; i++) { | 68 | @@ -XXX,XX +XXX,XX @@ static int net_client_init1(const Netdev *netdev, bool is_netdev, Error **errp) |
34 | + NetClientState *nc = qemu_get_subqueue(nic, i); | ||
35 | + /* If this is a peer NIC and peer has already been deleted, free it now. */ | ||
36 | + if (nic->peer_deleted) { | ||
37 | + qemu_free_net_client(nc->peer); | ||
38 | + } else if (nc->peer) { | ||
39 | + /* if there are RX packets pending, complete them */ | ||
40 | + qemu_purge_queued_packets(nc->peer); | ||
41 | } | 69 | } |
42 | } | 70 | } |
43 | 71 | ||
72 | + nc = qemu_find_netdev(netdev->id); | ||
73 | + if (nc) { | ||
74 | + error_setg(errp, "Duplicate ID '%s'", netdev->id); | ||
75 | + return -1; | ||
76 | + } | ||
77 | + | ||
78 | if (net_client_init_fun[netdev->type](netdev, netdev->id, peer, errp) < 0) { | ||
79 | /* FIXME drop when all init functions store an Error */ | ||
80 | if (errp && !*errp) { | ||
81 | @@ -XXX,XX +XXX,XX @@ static int net_client_init1(const Netdev *netdev, bool is_netdev, Error **errp) | ||
82 | } | ||
83 | |||
84 | if (is_netdev) { | ||
85 | - NetClientState *nc; | ||
86 | - | ||
87 | nc = qemu_find_netdev(netdev->id); | ||
88 | assert(nc); | ||
89 | nc->is_netdev = true; | ||
90 | @@ -XXX,XX +XXX,XX @@ void qmp_netdev_add(Netdev *netdev, Error **errp) | ||
91 | void qmp_netdev_del(const char *id, Error **errp) | ||
92 | { | ||
93 | NetClientState *nc; | ||
94 | + QemuOpts *opts; | ||
95 | |||
96 | nc = qemu_find_netdev(id); | ||
97 | if (!nc) { | ||
98 | @@ -XXX,XX +XXX,XX @@ void qmp_netdev_del(const char *id, Error **errp) | ||
99 | } | ||
100 | |||
101 | qemu_del_net_client(nc); | ||
102 | + | ||
103 | + /* | ||
104 | + * Wart: we need to delete the QemuOpts associated with netdevs | ||
105 | + * created via CLI or HMP, to avoid bogus "Duplicate ID" errors in | ||
106 | + * HMP netdev_add. | ||
107 | + */ | ||
108 | + opts = qemu_opts_find(qemu_find_opts("netdev"), id); | ||
109 | + if (opts) { | ||
110 | + qemu_opts_del(opts); | ||
111 | + } | ||
112 | } | ||
113 | |||
114 | static void netfilter_print_info(Monitor *mon, NetFilterState *nf) | ||
44 | -- | 115 | -- |
45 | 2.7.4 | 116 | 2.7.4 |
46 | 117 | ||
47 | 118 | diff view generated by jsdifflib |
1 | From: Keqian Zhu <zhukeqian1@huawei.com> | 1 | From: Markus Carlstedt <markus.carlstedt@windriver.com> |
---|---|---|---|
2 | 2 | ||
3 | Fixes: 63c4db4c2e6d (net: relocate paths to helpers and scripts) | 3 | To calculate the TCP/UDP checksum we need the whole datagram. Unless |
4 | Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com> | 4 | the hardware has some logic to collect all fragments before sending |
5 | the whole datagram first, it can only be done by the network stack, | ||
6 | which is normally the case for the NICs we have seen so far. | ||
7 | |||
8 | Skip these fragmented IP packets to avoid checksum corruption. | ||
9 | |||
10 | Signed-off-by: Markus Carlstedt <markus.carlstedt@windriver.com> | ||
11 | Signed-off-by: Bin Meng <bin.meng@windriver.com> | ||
5 | Signed-off-by: Jason Wang <jasowang@redhat.com> | 12 | Signed-off-by: Jason Wang <jasowang@redhat.com> |
6 | --- | 13 | --- |
7 | net/tap.c | 3 ++- | 14 | net/checksum.c | 4 ++++ |
8 | 1 file changed, 2 insertions(+), 1 deletion(-) | 15 | 1 file changed, 4 insertions(+) |
9 | 16 | ||
10 | diff --git a/net/tap.c b/net/tap.c | 17 | diff --git a/net/checksum.c b/net/checksum.c |
11 | index XXXXXXX..XXXXXXX 100644 | 18 | index XXXXXXX..XXXXXXX 100644 |
12 | --- a/net/tap.c | 19 | --- a/net/checksum.c |
13 | +++ b/net/tap.c | 20 | +++ b/net/checksum.c |
14 | @@ -XXX,XX +XXX,XX @@ free_fail: | 21 | @@ -XXX,XX +XXX,XX @@ void net_checksum_calculate(uint8_t *data, int length) |
15 | script = default_script = get_relocated_path(DEFAULT_NETWORK_SCRIPT); | 22 | return; /* not IPv4 */ |
16 | } | 23 | } |
17 | if (!downscript) { | 24 | |
18 | - downscript = default_downscript = get_relocated_path(DEFAULT_NETWORK_SCRIPT); | 25 | + if (IP4_IS_FRAGMENT(ip)) { |
19 | + downscript = default_downscript = | 26 | + return; /* a fragmented IP packet */ |
20 | + get_relocated_path(DEFAULT_NETWORK_DOWN_SCRIPT); | 27 | + } |
21 | } | 28 | + |
22 | 29 | ip_len = lduw_be_p(&ip->ip_len); | |
23 | if (tap->has_ifname) { | 30 | |
31 | /* Last, check that we have enough data for the all IP frame */ | ||
24 | -- | 32 | -- |
25 | 2.7.4 | 33 | 2.7.4 |
26 | 34 | ||
27 | 35 | diff view generated by jsdifflib |
1 | From: yuanjungong <ruc_gongyuanjun@163.com> | 1 | From: Guishan Qin <guishan.qin@windriver.com> |
---|---|---|---|
2 | 2 | ||
3 | Close fd before returning. | 3 | At present net_checksum_calculate() only calculates TCP/UDP checksum |
4 | in an IP packet, but assumes the IP header checksum to be provided | ||
5 | by the software, e.g.: Linux kernel always calculates the IP header | ||
6 | checksum. However this might not always be the case, e.g.: for an IP | ||
7 | checksum offload enabled stack like VxWorks, the IP header checksum | ||
8 | can be zero. | ||
4 | 9 | ||
5 | Buglink: https://bugs.launchpad.net/qemu/+bug/1904486 | 10 | This adds the checksum calculation of the IP header. |
6 | 11 | ||
7 | Signed-off-by: yuanjungong <ruc_gongyuanjun@163.com> | 12 | Signed-off-by: Guishan Qin <guishan.qin@windriver.com> |
8 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 13 | Signed-off-by: Yabing Liu <yabing.liu@windriver.com> |
14 | Signed-off-by: Bin Meng <bin.meng@windriver.com> | ||
15 | Reviewed-by: Cédric Le Goater <clg@kaod.org> | ||
9 | Signed-off-by: Jason Wang <jasowang@redhat.com> | 16 | Signed-off-by: Jason Wang <jasowang@redhat.com> |
10 | --- | 17 | --- |
11 | net/tap.c | 2 ++ | 18 | net/checksum.c | 8 ++++++-- |
12 | 1 file changed, 2 insertions(+) | 19 | 1 file changed, 6 insertions(+), 2 deletions(-) |
13 | 20 | ||
14 | diff --git a/net/tap.c b/net/tap.c | 21 | diff --git a/net/checksum.c b/net/checksum.c |
15 | index XXXXXXX..XXXXXXX 100644 | 22 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/net/tap.c | 23 | --- a/net/checksum.c |
17 | +++ b/net/tap.c | 24 | +++ b/net/checksum.c |
18 | @@ -XXX,XX +XXX,XX @@ int net_init_tap(const Netdev *netdev, const char *name, | 25 | @@ -XXX,XX +XXX,XX @@ void net_checksum_calculate(uint8_t *data, int length) |
19 | if (ret < 0) { | 26 | { |
20 | error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d", | 27 | int mac_hdr_len, ip_len; |
21 | name, fd); | 28 | struct ip_header *ip; |
22 | + close(fd); | 29 | + uint16_t csum; |
23 | return -1; | 30 | |
24 | } | 31 | /* |
25 | 32 | * Note: We cannot assume "data" is aligned, so the all code uses | |
26 | @@ -XXX,XX +XXX,XX @@ int net_init_tap(const Netdev *netdev, const char *name, | 33 | @@ -XXX,XX +XXX,XX @@ void net_checksum_calculate(uint8_t *data, int length) |
27 | vhostfdname, vnet_hdr, fd, &err); | 34 | return; /* not IPv4 */ |
28 | if (err) { | 35 | } |
29 | error_propagate(errp, err); | 36 | |
30 | + close(fd); | 37 | + /* Calculate IP checksum */ |
31 | return -1; | 38 | + stw_he_p(&ip->ip_sum, 0); |
32 | } | 39 | + csum = net_raw_checksum((uint8_t *)ip, IP_HDR_GET_LEN(ip)); |
33 | } else if (tap->has_fds) { | 40 | + stw_be_p(&ip->ip_sum, csum); |
41 | + | ||
42 | if (IP4_IS_FRAGMENT(ip)) { | ||
43 | return; /* a fragmented IP packet */ | ||
44 | } | ||
45 | @@ -XXX,XX +XXX,XX @@ void net_checksum_calculate(uint8_t *data, int length) | ||
46 | switch (ip->ip_p) { | ||
47 | case IP_PROTO_TCP: | ||
48 | { | ||
49 | - uint16_t csum; | ||
50 | tcp_header *tcp = (tcp_header *)(ip + 1); | ||
51 | |||
52 | if (ip_len < sizeof(tcp_header)) { | ||
53 | @@ -XXX,XX +XXX,XX @@ void net_checksum_calculate(uint8_t *data, int length) | ||
54 | } | ||
55 | case IP_PROTO_UDP: | ||
56 | { | ||
57 | - uint16_t csum; | ||
58 | udp_header *udp = (udp_header *)(ip + 1); | ||
59 | |||
60 | if (ip_len < sizeof(udp_header)) { | ||
34 | -- | 61 | -- |
35 | 2.7.4 | 62 | 2.7.4 |
36 | 63 | ||
37 | 64 | diff view generated by jsdifflib |
1 | From: Paolo Bonzini <pbonzini@redhat.com> | 1 | From: Bin Meng <bin.meng@windriver.com> |
---|---|---|---|
2 | 2 | ||
3 | "netdev_add help" is causing QEMU to exit because the code that | 3 | At present net_checksum_calculate() blindly calculates all types of |
4 | invokes show_netdevs is shared between CLI and HMP processing. | 4 | checksums (IP, TCP, UDP). Some NICs may have a per type setting in |
5 | Move the check to the callers so that exit(0) remains only | 5 | their BDs to control what checksum should be offloaded. To support |
6 | in the CLI flow. | 6 | such hardware behavior, introduce a 'csum_flag' parameter to the |
7 | 7 | net_checksum_calculate() API to allow fine control over what type | |
8 | "netdev_add help" is not fixed by this patch; that is left for | 8 | checksum is calculated. |
9 | later work. | 9 | |
10 | 10 | Existing users of this API are updated accordingly. | |
11 | Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> | 11 | |
12 | Signed-off-by: Bin Meng <bin.meng@windriver.com> | ||
12 | Signed-off-by: Jason Wang <jasowang@redhat.com> | 13 | Signed-off-by: Jason Wang <jasowang@redhat.com> |
13 | --- | 14 | --- |
14 | include/net/net.h | 1 + | 15 | hw/net/allwinner-sun8i-emac.c | 2 +- |
15 | monitor/hmp-cmds.c | 6 +++++ | 16 | hw/net/cadence_gem.c | 2 +- |
16 | net/net.c | 68 +++++++++++++++++++++++++++--------------------------- | 17 | hw/net/fsl_etsec/rings.c | 18 +++++++++--------- |
17 | 3 files changed, 41 insertions(+), 34 deletions(-) | 18 | hw/net/ftgmac100.c | 13 ++++++++++++- |
18 | 19 | hw/net/imx_fec.c | 20 ++++++++------------ | |
19 | diff --git a/include/net/net.h b/include/net/net.h | 20 | hw/net/virtio-net.c | 2 +- |
20 | index XXXXXXX..XXXXXXX 100644 | 21 | hw/net/xen_nic.c | 2 +- |
21 | --- a/include/net/net.h | 22 | include/net/checksum.h | 7 ++++++- |
22 | +++ b/include/net/net.h | 23 | net/checksum.c | 18 ++++++++++++++---- |
23 | @@ -XXX,XX +XXX,XX @@ extern const char *host_net_devices[]; | 24 | net/filter-rewriter.c | 4 ++-- |
24 | 25 | 10 files changed, 55 insertions(+), 33 deletions(-) | |
25 | /* from net.c */ | 26 | |
26 | int net_client_parse(QemuOptsList *opts_list, const char *str); | 27 | diff --git a/hw/net/allwinner-sun8i-emac.c b/hw/net/allwinner-sun8i-emac.c |
27 | +void show_netdevs(void); | 28 | index XXXXXXX..XXXXXXX 100644 |
28 | int net_init_clients(Error **errp); | 29 | --- a/hw/net/allwinner-sun8i-emac.c |
29 | void net_check_clients(void); | 30 | +++ b/hw/net/allwinner-sun8i-emac.c |
30 | void net_cleanup(void); | 31 | @@ -XXX,XX +XXX,XX @@ static void allwinner_sun8i_emac_transmit(AwSun8iEmacState *s) |
31 | diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c | 32 | /* After the last descriptor, send the packet */ |
32 | index XXXXXXX..XXXXXXX 100644 | 33 | if (desc.status2 & TX_DESC_STATUS2_LAST_DESC) { |
33 | --- a/monitor/hmp-cmds.c | 34 | if (desc.status2 & TX_DESC_STATUS2_CHECKSUM_MASK) { |
34 | +++ b/monitor/hmp-cmds.c | 35 | - net_checksum_calculate(packet_buf, packet_bytes); |
36 | + net_checksum_calculate(packet_buf, packet_bytes, CSUM_ALL); | ||
37 | } | ||
38 | |||
39 | qemu_send_packet(nc, packet_buf, packet_bytes); | ||
40 | diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c | ||
41 | index XXXXXXX..XXXXXXX 100644 | ||
42 | --- a/hw/net/cadence_gem.c | ||
43 | +++ b/hw/net/cadence_gem.c | ||
44 | @@ -XXX,XX +XXX,XX @@ static void gem_transmit(CadenceGEMState *s) | ||
45 | |||
46 | /* Is checksum offload enabled? */ | ||
47 | if (s->regs[GEM_DMACFG] & GEM_DMACFG_TXCSUM_OFFL) { | ||
48 | - net_checksum_calculate(s->tx_packet, total_bytes); | ||
49 | + net_checksum_calculate(s->tx_packet, total_bytes, CSUM_ALL); | ||
50 | } | ||
51 | |||
52 | /* Update MAC statistics */ | ||
53 | diff --git a/hw/net/fsl_etsec/rings.c b/hw/net/fsl_etsec/rings.c | ||
54 | index XXXXXXX..XXXXXXX 100644 | ||
55 | --- a/hw/net/fsl_etsec/rings.c | ||
56 | +++ b/hw/net/fsl_etsec/rings.c | ||
57 | @@ -XXX,XX +XXX,XX @@ static void process_tx_fcb(eTSEC *etsec) | ||
58 | uint8_t *l3_header = etsec->tx_buffer + 8 + l3_header_offset; | ||
59 | /* L4 header */ | ||
60 | uint8_t *l4_header = l3_header + l4_header_offset; | ||
61 | + int csum = 0; | ||
62 | |||
63 | /* if packet is IP4 and IP checksum is requested */ | ||
64 | if (flags & FCB_TX_IP && flags & FCB_TX_CIP) { | ||
65 | - /* do IP4 checksum (TODO This function does TCP/UDP checksum | ||
66 | - * but not sure if it also does IP4 checksum.) */ | ||
67 | - net_checksum_calculate(etsec->tx_buffer + 8, | ||
68 | - etsec->tx_buffer_len - 8); | ||
69 | + csum |= CSUM_IP; | ||
70 | } | ||
71 | /* TODO Check the correct usage of the PHCS field of the FCB in case the NPH | ||
72 | * flag is on */ | ||
73 | @@ -XXX,XX +XXX,XX @@ static void process_tx_fcb(eTSEC *etsec) | ||
74 | /* if checksum is requested */ | ||
75 | if (flags & FCB_TX_CTU) { | ||
76 | /* do UDP checksum */ | ||
77 | - | ||
78 | - net_checksum_calculate(etsec->tx_buffer + 8, | ||
79 | - etsec->tx_buffer_len - 8); | ||
80 | + csum |= CSUM_UDP; | ||
81 | } else { | ||
82 | /* set checksum field to 0 */ | ||
83 | l4_header[6] = 0; | ||
84 | @@ -XXX,XX +XXX,XX @@ static void process_tx_fcb(eTSEC *etsec) | ||
85 | } | ||
86 | } else if (flags & FCB_TX_CTU) { /* if TCP and checksum is requested */ | ||
87 | /* do TCP checksum */ | ||
88 | - net_checksum_calculate(etsec->tx_buffer + 8, | ||
89 | - etsec->tx_buffer_len - 8); | ||
90 | + csum |= CSUM_TCP; | ||
91 | } | ||
92 | } | ||
93 | + | ||
94 | + if (csum) { | ||
95 | + net_checksum_calculate(etsec->tx_buffer + 8, | ||
96 | + etsec->tx_buffer_len - 8, csum); | ||
97 | + } | ||
98 | } | ||
99 | |||
100 | static void process_tx_bd(eTSEC *etsec, | ||
101 | diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c | ||
102 | index XXXXXXX..XXXXXXX 100644 | ||
103 | --- a/hw/net/ftgmac100.c | ||
104 | +++ b/hw/net/ftgmac100.c | ||
105 | @@ -XXX,XX +XXX,XX @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring, | ||
106 | ptr += len; | ||
107 | frame_size += len; | ||
108 | if (bd.des0 & FTGMAC100_TXDES0_LTS) { | ||
109 | + int csum = 0; | ||
110 | |||
111 | /* Check for VLAN */ | ||
112 | if (flags & FTGMAC100_TXDES1_INS_VLANTAG && | ||
113 | @@ -XXX,XX +XXX,XX @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring, | ||
114 | } | ||
115 | |||
116 | if (flags & FTGMAC100_TXDES1_IP_CHKSUM) { | ||
117 | - net_checksum_calculate(s->frame, frame_size); | ||
118 | + csum |= CSUM_IP; | ||
119 | } | ||
120 | + if (flags & FTGMAC100_TXDES1_TCP_CHKSUM) { | ||
121 | + csum |= CSUM_TCP; | ||
122 | + } | ||
123 | + if (flags & FTGMAC100_TXDES1_UDP_CHKSUM) { | ||
124 | + csum |= CSUM_UDP; | ||
125 | + } | ||
126 | + if (csum) { | ||
127 | + net_checksum_calculate(s->frame, frame_size, csum); | ||
128 | + } | ||
129 | + | ||
130 | /* Last buffer in frame. */ | ||
131 | qemu_send_packet(qemu_get_queue(s->nic), s->frame, frame_size); | ||
132 | ptr = s->frame; | ||
133 | diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c | ||
134 | index XXXXXXX..XXXXXXX 100644 | ||
135 | --- a/hw/net/imx_fec.c | ||
136 | +++ b/hw/net/imx_fec.c | ||
137 | @@ -XXX,XX +XXX,XX @@ static void imx_enet_do_tx(IMXFECState *s, uint32_t index) | ||
138 | ptr += len; | ||
139 | frame_size += len; | ||
140 | if (bd.flags & ENET_BD_L) { | ||
141 | + int csum = 0; | ||
142 | + | ||
143 | if (bd.option & ENET_BD_PINS) { | ||
144 | - struct ip_header *ip_hd = PKT_GET_IP_HDR(s->frame); | ||
145 | - if (IP_HEADER_VERSION(ip_hd) == 4) { | ||
146 | - net_checksum_calculate(s->frame, frame_size); | ||
147 | - } | ||
148 | + csum |= (CSUM_TCP | CSUM_UDP); | ||
149 | } | ||
150 | if (bd.option & ENET_BD_IINS) { | ||
151 | - struct ip_header *ip_hd = PKT_GET_IP_HDR(s->frame); | ||
152 | - /* We compute checksum only for IPv4 frames */ | ||
153 | - if (IP_HEADER_VERSION(ip_hd) == 4) { | ||
154 | - uint16_t csum; | ||
155 | - ip_hd->ip_sum = 0; | ||
156 | - csum = net_raw_checksum((uint8_t *)ip_hd, sizeof(*ip_hd)); | ||
157 | - ip_hd->ip_sum = cpu_to_be16(csum); | ||
158 | - } | ||
159 | + csum |= CSUM_IP; | ||
160 | + } | ||
161 | + if (csum) { | ||
162 | + net_checksum_calculate(s->frame, frame_size, csum); | ||
163 | } | ||
164 | + | ||
165 | /* Last buffer in frame. */ | ||
166 | |||
167 | qemu_send_packet(qemu_get_queue(s->nic), s->frame, frame_size); | ||
168 | diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c | ||
169 | index XXXXXXX..XXXXXXX 100644 | ||
170 | --- a/hw/net/virtio-net.c | ||
171 | +++ b/hw/net/virtio-net.c | ||
172 | @@ -XXX,XX +XXX,XX @@ static void work_around_broken_dhclient(struct virtio_net_hdr *hdr, | ||
173 | (buf[12] == 0x08 && buf[13] == 0x00) && /* ethertype == IPv4 */ | ||
174 | (buf[23] == 17) && /* ip.protocol == UDP */ | ||
175 | (buf[34] == 0 && buf[35] == 67)) { /* udp.srcport == bootps */ | ||
176 | - net_checksum_calculate(buf, size); | ||
177 | + net_checksum_calculate(buf, size, CSUM_UDP); | ||
178 | hdr->flags &= ~VIRTIO_NET_HDR_F_NEEDS_CSUM; | ||
179 | } | ||
180 | } | ||
181 | diff --git a/hw/net/xen_nic.c b/hw/net/xen_nic.c | ||
182 | index XXXXXXX..XXXXXXX 100644 | ||
183 | --- a/hw/net/xen_nic.c | ||
184 | +++ b/hw/net/xen_nic.c | ||
185 | @@ -XXX,XX +XXX,XX @@ static void net_tx_packets(struct XenNetDev *netdev) | ||
186 | tmpbuf = g_malloc(XC_PAGE_SIZE); | ||
187 | } | ||
188 | memcpy(tmpbuf, page + txreq.offset, txreq.size); | ||
189 | - net_checksum_calculate(tmpbuf, txreq.size); | ||
190 | + net_checksum_calculate(tmpbuf, txreq.size, CSUM_ALL); | ||
191 | qemu_send_packet(qemu_get_queue(netdev->nic), tmpbuf, | ||
192 | txreq.size); | ||
193 | } else { | ||
194 | diff --git a/include/net/checksum.h b/include/net/checksum.h | ||
195 | index XXXXXXX..XXXXXXX 100644 | ||
196 | --- a/include/net/checksum.h | ||
197 | +++ b/include/net/checksum.h | ||
35 | @@ -XXX,XX +XXX,XX @@ | 198 | @@ -XXX,XX +XXX,XX @@ |
36 | #include "qemu/option.h" | 199 | #include "qemu/bswap.h" |
37 | #include "qemu/timer.h" | 200 | struct iovec; |
38 | #include "qemu/sockets.h" | 201 | |
39 | +#include "qemu/help_option.h" | 202 | +#define CSUM_IP 0x01 |
40 | #include "monitor/monitor-internal.h" | 203 | +#define CSUM_TCP 0x02 |
41 | #include "qapi/error.h" | 204 | +#define CSUM_UDP 0x04 |
42 | #include "qapi/clone-visitor.h" | 205 | +#define CSUM_ALL (CSUM_IP | CSUM_TCP | CSUM_UDP) |
43 | @@ -XXX,XX +XXX,XX @@ void hmp_netdev_add(Monitor *mon, const QDict *qdict) | 206 | + |
207 | uint32_t net_checksum_add_cont(int len, uint8_t *buf, int seq); | ||
208 | uint16_t net_checksum_finish(uint32_t sum); | ||
209 | uint16_t net_checksum_tcpudp(uint16_t length, uint16_t proto, | ||
210 | uint8_t *addrs, uint8_t *buf); | ||
211 | -void net_checksum_calculate(uint8_t *data, int length); | ||
212 | +void net_checksum_calculate(uint8_t *data, int length, int csum_flag); | ||
213 | |||
214 | static inline uint32_t | ||
215 | net_checksum_add(int len, uint8_t *buf) | ||
216 | diff --git a/net/checksum.c b/net/checksum.c | ||
217 | index XXXXXXX..XXXXXXX 100644 | ||
218 | --- a/net/checksum.c | ||
219 | +++ b/net/checksum.c | ||
220 | @@ -XXX,XX +XXX,XX @@ uint16_t net_checksum_tcpudp(uint16_t length, uint16_t proto, | ||
221 | return net_checksum_finish(sum); | ||
222 | } | ||
223 | |||
224 | -void net_checksum_calculate(uint8_t *data, int length) | ||
225 | +void net_checksum_calculate(uint8_t *data, int length, int csum_flag) | ||
44 | { | 226 | { |
45 | Error *err = NULL; | 227 | int mac_hdr_len, ip_len; |
46 | QemuOpts *opts; | 228 | struct ip_header *ip; |
47 | + const char *type = qdict_get_try_str(qdict, "type"); | 229 | @@ -XXX,XX +XXX,XX @@ void net_checksum_calculate(uint8_t *data, int length) |
48 | 230 | } | |
49 | + if (type && is_help_option(type)) { | 231 | |
50 | + show_netdevs(); | 232 | /* Calculate IP checksum */ |
51 | + return; | 233 | - stw_he_p(&ip->ip_sum, 0); |
234 | - csum = net_raw_checksum((uint8_t *)ip, IP_HDR_GET_LEN(ip)); | ||
235 | - stw_be_p(&ip->ip_sum, csum); | ||
236 | + if (csum_flag & CSUM_IP) { | ||
237 | + stw_he_p(&ip->ip_sum, 0); | ||
238 | + csum = net_raw_checksum((uint8_t *)ip, IP_HDR_GET_LEN(ip)); | ||
239 | + stw_be_p(&ip->ip_sum, csum); | ||
52 | + } | 240 | + } |
53 | opts = qemu_opts_from_qdict(qemu_find_opts("netdev"), qdict, &err); | 241 | |
54 | if (err) { | 242 | if (IP4_IS_FRAGMENT(ip)) { |
55 | goto out; | 243 | return; /* a fragmented IP packet */ |
56 | diff --git a/net/net.c b/net/net.c | 244 | @@ -XXX,XX +XXX,XX @@ void net_checksum_calculate(uint8_t *data, int length) |
57 | index XXXXXXX..XXXXXXX 100644 | 245 | switch (ip->ip_p) { |
58 | --- a/net/net.c | 246 | case IP_PROTO_TCP: |
59 | +++ b/net/net.c | 247 | { |
60 | @@ -XXX,XX +XXX,XX @@ | 248 | + if (!(csum_flag & CSUM_TCP)) { |
61 | #include "qemu/config-file.h" | 249 | + return; |
62 | #include "qemu/ctype.h" | ||
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 | } | ||
87 | } | ||
88 | |||
89 | @@ -XXX,XX +XXX,XX @@ static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp) | ||
90 | int ret = -1; | ||
91 | Visitor *v = opts_visitor_new(opts); | ||
92 | |||
93 | - const char *type = qemu_opt_get(opts, "type"); | ||
94 | - | ||
95 | - if (is_netdev && type && is_help_option(type)) { | ||
96 | - show_netdevs(); | ||
97 | - exit(0); | ||
98 | - } else { | ||
99 | - /* Parse convenience option format ip6-net=fec0::0[/64] */ | ||
100 | - const char *ip6_net = qemu_opt_get(opts, "ipv6-net"); | ||
101 | + /* Parse convenience option format ip6-net=fec0::0[/64] */ | ||
102 | + const char *ip6_net = qemu_opt_get(opts, "ipv6-net"); | ||
103 | |||
104 | - if (ip6_net) { | ||
105 | - char *prefix_addr; | ||
106 | - unsigned long prefix_len = 64; /* Default 64bit prefix length. */ | ||
107 | + if (ip6_net) { | ||
108 | + char *prefix_addr; | ||
109 | + unsigned long prefix_len = 64; /* Default 64bit prefix length. */ | ||
110 | |||
111 | - substrings = g_strsplit(ip6_net, "/", 2); | ||
112 | - if (!substrings || !substrings[0]) { | ||
113 | - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "ipv6-net", | ||
114 | - "a valid IPv6 prefix"); | ||
115 | - goto out; | ||
116 | - } | ||
117 | + substrings = g_strsplit(ip6_net, "/", 2); | ||
118 | + if (!substrings || !substrings[0]) { | ||
119 | + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "ipv6-net", | ||
120 | + "a valid IPv6 prefix"); | ||
121 | + goto out; | ||
122 | + } | 250 | + } |
123 | 251 | + | |
124 | - prefix_addr = substrings[0]; | 252 | tcp_header *tcp = (tcp_header *)(ip + 1); |
125 | + prefix_addr = substrings[0]; | 253 | |
126 | 254 | if (ip_len < sizeof(tcp_header)) { | |
127 | - /* Handle user-specified prefix length. */ | 255 | @@ -XXX,XX +XXX,XX @@ void net_checksum_calculate(uint8_t *data, int length) |
128 | - if (substrings[1] && | 256 | } |
129 | - qemu_strtoul(substrings[1], NULL, 10, &prefix_len)) | 257 | case IP_PROTO_UDP: |
130 | - { | 258 | { |
131 | - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, | 259 | + if (!(csum_flag & CSUM_UDP)) { |
132 | - "ipv6-prefixlen", "a number"); | 260 | + return; |
133 | - goto out; | 261 | + } |
134 | - } | 262 | + |
135 | - | 263 | udp_header *udp = (udp_header *)(ip + 1); |
136 | - qemu_opt_set(opts, "ipv6-prefix", prefix_addr, &error_abort); | 264 | |
137 | - qemu_opt_set_number(opts, "ipv6-prefixlen", prefix_len, | 265 | if (ip_len < sizeof(udp_header)) { |
138 | - &error_abort); | 266 | diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c |
139 | - qemu_opt_unset(opts, "ipv6-net"); | 267 | index XXXXXXX..XXXXXXX 100644 |
140 | + /* Handle user-specified prefix length. */ | 268 | --- a/net/filter-rewriter.c |
141 | + if (substrings[1] && | 269 | +++ b/net/filter-rewriter.c |
142 | + qemu_strtoul(substrings[1], NULL, 10, &prefix_len)) | 270 | @@ -XXX,XX +XXX,XX @@ static int handle_primary_tcp_pkt(RewriterState *rf, |
143 | + { | 271 | tcp_pkt->th_ack = htonl(ntohl(tcp_pkt->th_ack) + conn->offset); |
144 | + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, | 272 | |
145 | + "ipv6-prefixlen", "a number"); | 273 | net_checksum_calculate((uint8_t *)pkt->data + pkt->vnet_hdr_len, |
146 | + goto out; | 274 | - pkt->size - pkt->vnet_hdr_len); |
275 | + pkt->size - pkt->vnet_hdr_len, CSUM_TCP); | ||
147 | } | 276 | } |
148 | + | 277 | |
149 | + qemu_opt_set(opts, "ipv6-prefix", prefix_addr, &error_abort); | 278 | /* |
150 | + qemu_opt_set_number(opts, "ipv6-prefixlen", prefix_len, | 279 | @@ -XXX,XX +XXX,XX @@ static int handle_secondary_tcp_pkt(RewriterState *rf, |
151 | + &error_abort); | 280 | tcp_pkt->th_seq = htonl(ntohl(tcp_pkt->th_seq) - conn->offset); |
152 | + qemu_opt_unset(opts, "ipv6-net"); | 281 | |
153 | } | 282 | net_checksum_calculate((uint8_t *)pkt->data + pkt->vnet_hdr_len, |
154 | 283 | - pkt->size - pkt->vnet_hdr_len); | |
155 | /* Create an ID for -net if the user did not specify one */ | 284 | + pkt->size - pkt->vnet_hdr_len, CSUM_TCP); |
156 | @@ -XXX,XX +XXX,XX @@ static int net_init_client(void *dummy, QemuOpts *opts, Error **errp) | 285 | } |
157 | 286 | } | |
158 | static int net_init_netdev(void *dummy, QemuOpts *opts, Error **errp) | ||
159 | { | ||
160 | + const char *type = qemu_opt_get(opts, "type"); | ||
161 | + | ||
162 | + if (type && is_help_option(type)) { | ||
163 | + show_netdevs(); | ||
164 | + exit(0); | ||
165 | + } | ||
166 | return net_client_init(opts, true, errp); | ||
167 | } | ||
168 | 287 | ||
169 | -- | 288 | -- |
170 | 2.7.4 | 289 | 2.7.4 |
171 | 290 | ||
172 | 291 | diff view generated by jsdifflib |