1
The following changes since commit 2e02083438962d26ef9dcc7100f3b378104183db:
1
The following changes since commit bdee969c0e65d4d509932b1d70e3a3b2ffbff6d5:
2
2
3
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging (2017-11-17 19:08:07 +0000)
3
Merge remote-tracking branch 'remotes/bonzini-gitlab/tags/for-upstream' into staging (2021-03-19 18:01:17 +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 c527e0afcd7d719abc3a5ca5e4c8ac2fe48b999f:
9
for you to fetch changes up to c7274b5ef43614dd133daec1e2018f71d8744088:
10
10
11
hw/net/vmxnet3: Fix code to work on big endian hosts, too (2017-11-20 11:08:00 +0800)
11
net/eth: Add an assert() and invert if() statement to simplify code (2021-03-22 17:34:31 +0800)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
14
15
----------------------------------------------------------------
15
----------------------------------------------------------------
16
Ed Swierk (1):
16
Bin Meng (4):
17
net: Transmit zero UDP checksum as 0xFFFF
17
net: eth: Add a helper to pad a short Ethernet frame
18
net: Add a 'do_not_pad" to NetClientState
19
net: Pad short frames to minimum size before sending from SLiRP/TAP
20
hw/net: virtio-net: Initialize nc->do_not_pad to true
18
21
19
Jason Wang (1):
22
Lukas Straub (2):
20
Revert "Add new PCI ID for i82559a"
23
net/colo-compare.c: Fix memory leak for non-tcp packet
24
net/colo-compare.c: Optimize removal of secondary packet
21
25
22
Mao Zhongyi (1):
26
Philippe Mathieu-Daudé (7):
23
colo-compare: fix the dangerous assignment
27
net/eth: Use correct in6_address offset in _eth_get_rss_ex_dst_addr()
28
net/eth: Simplify _eth_get_rss_ex_dst_addr()
29
net/eth: Better describe _eth_get_rss_ex_dst_addr's offset argument
30
net/eth: Check size earlier in _eth_get_rss_ex_dst_addr()
31
net/eth: Check iovec has enough data earlier
32
net/eth: Read ip6_ext_hdr_routing buffer before accessing it
33
net/eth: Add an assert() and invert if() statement to simplify code
24
34
25
Stefan Weil (1):
35
MAINTAINERS | 1 +
26
MAINTAINERS: Add missing entry for eepro100 emulation
36
hw/net/virtio-net.c | 4 +++
27
37
include/net/eth.h | 17 ++++++++++++
28
Thomas Huth (2):
38
include/net/net.h | 1 +
29
hw/net/eepro100: Fix endianness problem on big endian hosts
39
net/colo-compare.c | 3 ++-
30
hw/net/vmxnet3: Fix code to work on big endian hosts, too
40
net/eth.c | 61 +++++++++++++++++++++++++++---------------
31
41
net/slirp.c | 10 +++++++
32
MAINTAINERS | 5 ++
42
net/tap-win32.c | 10 +++++++
33
hw/net/e1000.c | 2 +-
43
net/tap.c | 10 +++++++
34
hw/net/eepro100.c | 17 +---
44
tests/qtest/fuzz-e1000e-test.c | 53 ++++++++++++++++++++++++++++++++++++
35
hw/net/net_rx_pkt.c | 2 +-
45
tests/qtest/meson.build | 1 +
36
hw/net/net_tx_pkt.c | 2 +-
46
11 files changed, 148 insertions(+), 23 deletions(-)
37
hw/net/vmware_utils.h | 6 ++
47
create mode 100644 tests/qtest/fuzz-e1000e-test.c
38
hw/net/vmxnet3.c | 49 ++++++++---
39
hw/net/vmxnet3.h | 230 ++++++++++++++++++++++++++++++-------------------
40
include/hw/compat.h | 4 -
41
include/hw/pci/pci.h | 1 -
42
include/net/checksum.h | 6 ++
43
net/colo-compare.c | 2 +-
44
qemu-options.hx | 2 +-
45
13 files changed, 201 insertions(+), 127 deletions(-)
46
48
47
49
diff view generated by jsdifflib
New patch
1
From: Bin Meng <bmeng.cn@gmail.com>
1
2
3
Add a helper to pad a short Ethernet frame to the minimum required
4
length, which can be used by backends' code.
5
6
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
10
include/net/eth.h | 17 +++++++++++++++++
11
net/eth.c | 17 +++++++++++++++++
12
2 files changed, 34 insertions(+)
13
14
diff --git a/include/net/eth.h b/include/net/eth.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/net/eth.h
17
+++ b/include/net/eth.h
18
@@ -XXX,XX +XXX,XX @@
19
20
#define ETH_ALEN 6
21
#define ETH_HLEN 14
22
+#define ETH_ZLEN 60 /* Min. octets in frame without FCS */
23
24
struct eth_header {
25
uint8_t h_dest[ETH_ALEN]; /* destination eth addr */
26
@@ -XXX,XX +XXX,XX @@ bool
27
eth_parse_ipv6_hdr(const struct iovec *pkt, int pkt_frags,
28
size_t ip6hdr_off, eth_ip6_hdr_info *info);
29
30
+/**
31
+ * eth_pad_short_frame - pad a short frame to the minimum Ethernet frame length
32
+ *
33
+ * If the Ethernet frame size is shorter than 60 bytes, it will be padded to
34
+ * 60 bytes at the address @padded_pkt.
35
+ *
36
+ * @padded_pkt: buffer address to hold the padded frame
37
+ * @padded_buflen: pointer holding length of @padded_pkt. If the frame is
38
+ * padded, the length will be updated to the padded one.
39
+ * @pkt: address to hold the original Ethernet frame
40
+ * @pkt_size: size of the original Ethernet frame
41
+ * @return true if the frame is padded, otherwise false
42
+ */
43
+bool eth_pad_short_frame(uint8_t *padded_pkt, size_t *padded_buflen,
44
+ const void *pkt, size_t pkt_size);
45
+
46
#endif
47
diff --git a/net/eth.c b/net/eth.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/net/eth.c
50
+++ b/net/eth.c
51
@@ -XXX,XX +XXX,XX @@ bool eth_parse_ipv6_hdr(const struct iovec *pkt, int pkt_frags,
52
info->l4proto = ext_hdr.ip6r_nxt;
53
return true;
54
}
55
+
56
+bool eth_pad_short_frame(uint8_t *padded_pkt, size_t *padded_buflen,
57
+ const void *pkt, size_t pkt_size)
58
+{
59
+ assert(padded_buflen && *padded_buflen >= ETH_ZLEN);
60
+
61
+ if (pkt_size >= ETH_ZLEN) {
62
+ return false;
63
+ }
64
+
65
+ /* pad to minimum Ethernet frame length */
66
+ memcpy(padded_pkt, pkt, pkt_size);
67
+ memset(&padded_pkt[pkt_size], 0, ETH_ZLEN - pkt_size);
68
+ *padded_buflen = ETH_ZLEN;
69
+
70
+ return true;
71
+}
72
--
73
2.7.4
74
75
diff view generated by jsdifflib
1
This reverts commit 5e89dc01133f8f5e621f6b66b356c6f37d31dafb since:
1
From: Bin Meng <bmeng.cn@gmail.com>
2
2
3
- we should use ID in the spec instead the one used by OEM
3
This adds a flag in NetClientState, so that a net client can tell
4
- in the future, we should allow changing id through either property
4
its peer that the packets do not need to be padded to the minimum
5
or EEPROM file.
5
size of an Ethernet frame (60 bytes) before sending to it.
6
6
7
Cc: Stefan Weil <sw@weilnetz.de>
7
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
8
Cc: Michael Nawrocki <michael.nawrocki@gtri.gatech.edu>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Cc: Peter Maydell <peter.maydell@linaro.org>
10
Cc: Michael S. Tsirkin <mst@redhat.com>
11
Reviewed-by: Stefan Weil <sw@weilnetz.de>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
---
10
---
14
hw/net/eepro100.c | 13 -------------
11
include/net/net.h | 1 +
15
include/hw/compat.h | 4 ----
12
1 file changed, 1 insertion(+)
16
include/hw/pci/pci.h | 1 -
17
qemu-options.hx | 2 +-
18
4 files changed, 1 insertion(+), 19 deletions(-)
19
13
20
diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
14
diff --git a/include/net/net.h b/include/net/net.h
21
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/net/eepro100.c
16
--- a/include/net/net.h
23
+++ b/hw/net/eepro100.c
17
+++ b/include/net/net.h
24
@@ -XXX,XX +XXX,XX @@ typedef struct {
18
@@ -XXX,XX +XXX,XX @@ struct NetClientState {
25
const char *name;
19
int vring_enable;
26
const char *desc;
20
int vnet_hdr_len;
27
uint16_t device_id;
21
bool is_netdev;
28
- uint16_t alt_device_id;
22
+ bool do_not_pad; /* do not pad to the minimum ethernet frame length */
29
uint8_t revision;
23
QTAILQ_HEAD(, NetFilterState) filters;
30
uint16_t subsystem_vendor_id;
31
uint16_t subsystem_id;
32
@@ -XXX,XX +XXX,XX @@ typedef struct {
33
/* Quasi static device properties (no need to save them). */
34
uint16_t stats_size;
35
bool has_extended_tcb_support;
36
- bool use_alt_device_id;
37
} EEPRO100State;
38
39
/* Word indices in EEPROM. */
40
@@ -XXX,XX +XXX,XX @@ static void e100_nic_realize(PCIDevice *pci_dev, Error **errp)
41
42
TRACE(OTHER, logout("\n"));
43
44
- /* By default, the i82559a adapter uses the legacy PCI ID (for the
45
- * i82557). This allows the PCI ID to be changed to the alternate
46
- * i82559 ID if needed.
47
- */
48
- if (s->use_alt_device_id && strcmp(info->name, "i82559a") == 0) {
49
- pci_config_set_device_id(s->dev.config, info->alt_device_id);
50
- }
51
-
52
s->device = info->device;
53
54
e100_pci_reset(s, &local_err);
55
@@ -XXX,XX +XXX,XX @@ static E100PCIDeviceInfo e100_devices[] = {
56
.desc = "Intel i82559A Ethernet",
57
.device = i82559A,
58
.device_id = PCI_DEVICE_ID_INTEL_82557,
59
- .alt_device_id = PCI_DEVICE_ID_INTEL_82559,
60
.revision = 0x06,
61
.stats_size = 80,
62
.has_extended_tcb_support = true,
63
@@ -XXX,XX +XXX,XX @@ static E100PCIDeviceInfo *eepro100_get_class(EEPRO100State *s)
64
65
static Property e100_properties[] = {
66
DEFINE_NIC_PROPERTIES(EEPRO100State, conf),
67
- DEFINE_PROP_BOOL("x-use-alt-device-id", EEPRO100State, use_alt_device_id,
68
- true),
69
DEFINE_PROP_END_OF_LIST(),
70
};
24
};
71
25
72
diff --git a/include/hw/compat.h b/include/hw/compat.h
73
index XXXXXXX..XXXXXXX 100644
74
--- a/include/hw/compat.h
75
+++ b/include/hw/compat.h
76
@@ -XXX,XX +XXX,XX @@
77
.driver = "virtio-tablet-device",\
78
.property = "wheel-axis",\
79
.value = "false",\
80
- },{\
81
- .driver = "i82559a",\
82
- .property = "x-use-alt-device-id",\
83
- .value = "false",\
84
},
85
86
#define HW_COMPAT_2_9 \
87
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
88
index XXXXXXX..XXXXXXX 100644
89
--- a/include/hw/pci/pci.h
90
+++ b/include/hw/pci/pci.h
91
@@ -XXX,XX +XXX,XX @@ extern bool pci_available;
92
/* Intel (0x8086) */
93
#define PCI_DEVICE_ID_INTEL_82551IT 0x1209
94
#define PCI_DEVICE_ID_INTEL_82557 0x1229
95
-#define PCI_DEVICE_ID_INTEL_82559 0x1030
96
#define PCI_DEVICE_ID_INTEL_82801IR 0x2922
97
98
/* Red Hat / Qumranet (for QEMU) -- see pci-ids.txt */
99
diff --git a/qemu-options.hx b/qemu-options.hx
100
index XXXXXXX..XXXXXXX 100644
101
--- a/qemu-options.hx
102
+++ b/qemu-options.hx
103
@@ -XXX,XX +XXX,XX @@ that the card should have; this option currently only affects virtio cards; set
104
@var{v} = 0 to disable MSI-X. If no @option{-net} option is specified, a single
105
NIC is created. QEMU can emulate several different models of network card.
106
Valid values for @var{type} are
107
-@code{virtio}, @code{i82551}, @code{i82557b}, @code{i82559a}, @code{i82559er},
108
+@code{virtio}, @code{i82551}, @code{i82557b}, @code{i82559er},
109
@code{ne2k_pci}, @code{ne2k_isa}, @code{pcnet}, @code{rtl8139},
110
@code{e1000}, @code{smc91c111}, @code{lance} and @code{mcf_fec}.
111
Not all devices are supported on all targets. Use @code{-net nic,model=help}
112
--
26
--
113
2.7.4
27
2.7.4
114
28
115
29
diff view generated by jsdifflib
New patch
1
From: Bin Meng <bmeng.cn@gmail.com>
1
2
3
The minimum Ethernet frame length is 60 bytes. For short frames with
4
smaller length like ARP packets (only 42 bytes), on a real world NIC
5
it can choose either padding its length to the minimum required 60
6
bytes, or sending it out directly to the wire. Such behavior can be
7
hardcoded or controled by a register bit. Similarly on the receive
8
path, NICs can choose either dropping such short frames directly or
9
handing them over to software to handle.
10
11
On the other hand, for the network backends like SLiRP/TAP, they
12
don't expose a way to control the short frame behavior. As of today
13
they just send/receive data from/to the other end connected to them,
14
which means any sized packet is acceptable. So they can send and
15
receive short frames without any problem. It is observed that ARP
16
packets sent from SLiRP/TAP are 42 bytes, and SLiRP/TAP just send
17
these ARP packets to the other end which might be a NIC model that
18
does not allow short frames to pass through.
19
20
To provide better compatibility, for packets sent from QEMU network
21
backends like SLiRP/TAP, we change to pad short frames before sending
22
it out to the other end, if the other end does not forbid it via the
23
nc->do_not_pad flag. This ensures a backend as an Ethernet sender
24
does not violate the spec. But with this change, the behavior of
25
dropping short frames from SLiRP/TAP interfaces in the NIC model
26
cannot be emulated because it always receives a packet that is spec
27
complaint. The capability of sending short frames from NIC models is
28
still supported and short frames can still pass through SLiRP/TAP.
29
30
This commit should be able to fix the issue as reported with some
31
NIC models before, that ARP requests get dropped, preventing the
32
guest from becoming visible on the network. It was workarounded in
33
these NIC models on the receive path, that when a short frame is
34
received, it is padded up to 60 bytes.
35
36
The following 2 commits seem to be the one to workaround this issue
37
in e1000 and vmxenet3 before, and should probably be reverted.
38
39
commit 78aeb23eded2 ("e1000: Pad short frames to minimum size (60 bytes)")
40
commit 40a87c6c9b11 ("vmxnet3: Pad short frames to minimum size (60 bytes)")
41
42
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
43
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
44
Signed-off-by: Jason Wang <jasowang@redhat.com>
45
---
46
net/slirp.c | 10 ++++++++++
47
net/tap-win32.c | 10 ++++++++++
48
net/tap.c | 10 ++++++++++
49
3 files changed, 30 insertions(+)
50
51
diff --git a/net/slirp.c b/net/slirp.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/net/slirp.c
54
+++ b/net/slirp.c
55
@@ -XXX,XX +XXX,XX @@
56
#include <pwd.h>
57
#include <sys/wait.h>
58
#endif
59
+#include "net/eth.h"
60
#include "net/net.h"
61
#include "clients.h"
62
#include "hub.h"
63
@@ -XXX,XX +XXX,XX @@ static ssize_t net_slirp_send_packet(const void *pkt, size_t pkt_len,
64
void *opaque)
65
{
66
SlirpState *s = opaque;
67
+ uint8_t min_pkt[ETH_ZLEN];
68
+ size_t min_pktsz = sizeof(min_pkt);
69
+
70
+ if (!s->nc.peer->do_not_pad) {
71
+ if (eth_pad_short_frame(min_pkt, &min_pktsz, pkt, pkt_len)) {
72
+ pkt = min_pkt;
73
+ pkt_len = min_pktsz;
74
+ }
75
+ }
76
77
return qemu_send_packet(&s->nc, pkt, pkt_len);
78
}
79
diff --git a/net/tap-win32.c b/net/tap-win32.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/net/tap-win32.c
82
+++ b/net/tap-win32.c
83
@@ -XXX,XX +XXX,XX @@
84
85
#include "qemu-common.h"
86
#include "clients.h" /* net_init_tap */
87
+#include "net/eth.h"
88
#include "net/net.h"
89
#include "net/tap.h" /* tap_has_ufo, ... */
90
#include "qemu/error-report.h"
91
@@ -XXX,XX +XXX,XX @@ static void tap_win32_send(void *opaque)
92
uint8_t *buf;
93
int max_size = 4096;
94
int size;
95
+ uint8_t min_pkt[ETH_ZLEN];
96
+ size_t min_pktsz = sizeof(min_pkt);
97
98
size = tap_win32_read(s->handle, &buf, max_size);
99
if (size > 0) {
100
+ if (!s->nc.peer->do_not_pad) {
101
+ if (eth_pad_short_frame(min_pkt, &min_pktsz, buf, size)) {
102
+ buf = min_pkt;
103
+ size = min_pktsz;
104
+ }
105
+ }
106
+
107
qemu_send_packet(&s->nc, buf, size);
108
tap_win32_free_buffer(s->handle, buf);
109
}
110
diff --git a/net/tap.c b/net/tap.c
111
index XXXXXXX..XXXXXXX 100644
112
--- a/net/tap.c
113
+++ b/net/tap.c
114
@@ -XXX,XX +XXX,XX @@
115
#include <sys/socket.h>
116
#include <net/if.h>
117
118
+#include "net/eth.h"
119
#include "net/net.h"
120
#include "clients.h"
121
#include "monitor/monitor.h"
122
@@ -XXX,XX +XXX,XX @@ static void tap_send(void *opaque)
123
124
while (true) {
125
uint8_t *buf = s->buf;
126
+ uint8_t min_pkt[ETH_ZLEN];
127
+ size_t min_pktsz = sizeof(min_pkt);
128
129
size = tap_read_packet(s->fd, s->buf, sizeof(s->buf));
130
if (size <= 0) {
131
@@ -XXX,XX +XXX,XX @@ static void tap_send(void *opaque)
132
size -= s->host_vnet_hdr_len;
133
}
134
135
+ if (!s->nc.peer->do_not_pad) {
136
+ if (eth_pad_short_frame(min_pkt, &min_pktsz, buf, size)) {
137
+ buf = min_pkt;
138
+ size = min_pktsz;
139
+ }
140
+ }
141
+
142
size = qemu_send_packet_async(&s->nc, buf, size, tap_send_completed);
143
if (size == 0) {
144
tap_read_poll(s, false);
145
--
146
2.7.4
147
148
diff view generated by jsdifflib
New patch
1
From: Bin Meng <bmeng.cn@gmail.com>
1
2
3
For virtio-net, there is no need to pad the Ethernet frame size to
4
60 bytes before sending to it.
5
6
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
9
hw/net/virtio-net.c | 4 ++++
10
1 file changed, 4 insertions(+)
11
12
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/net/virtio-net.c
15
+++ b/hw/net/virtio-net.c
16
@@ -XXX,XX +XXX,XX @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
17
object_get_typename(OBJECT(dev)), dev->id, n);
18
}
19
20
+ for (i = 0; i < n->max_queues; i++) {
21
+ n->nic->ncs[i].do_not_pad = true;
22
+ }
23
+
24
peer_test_vnet_hdr(n);
25
if (peer_has_vnet_hdr(n)) {
26
for (i = 0; i < n->max_queues; i++) {
27
--
28
2.7.4
29
30
diff view generated by jsdifflib
New patch
1
From: Lukas Straub <lukasstraub2@web.de>
1
2
3
Additional to removing the packet from the secondary queue,
4
we also need to free it.
5
6
Signed-off-by: Lukas Straub <lukasstraub2@web.de>
7
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
8
Reviewed-by: Zhang Chen <chen.zhang@intel.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
11
net/colo-compare.c | 1 +
12
1 file changed, 1 insertion(+)
13
14
diff --git a/net/colo-compare.c b/net/colo-compare.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/net/colo-compare.c
17
+++ b/net/colo-compare.c
18
@@ -XXX,XX +XXX,XX @@ static void colo_compare_packet(CompareState *s, Connection *conn,
19
20
if (result) {
21
colo_release_primary_pkt(s, pkt);
22
+ packet_destroy(result->data, NULL);
23
g_queue_remove(&conn->secondary_list, result->data);
24
} else {
25
/*
26
--
27
2.7.4
28
29
diff view generated by jsdifflib
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
1
From: Lukas Straub <lukasstraub2@web.de>
2
2
3
Cc: Peter Maydell <peter.maydell@linaro.org>
3
g_queue_remove needs to look up the list entry first, but we
4
Cc: Jason Wang <jasowang@redhat.com>
4
already have it as result and can remove it directly with
5
Cc: Zhang Chen <zhangckid@gmail.com>
5
g_queue_delete_link.
6
Cc: Li Zhijian <lizhijian@cn.fujitsu.com>
6
7
Cc: Paolo Bonzini <pbonzini@redhat.com>
7
Signed-off-by: Lukas Straub <lukasstraub2@web.de>
8
Fixes: 8ec14402029d783720f4312ed8a925548e1dad61
8
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
9
Reported-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Zhang Chen <chen.zhang@intel.com>
10
Reported-by: Paolo Bonzini <pbonzini@redhat.com>
11
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
12
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
13
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
14
---
11
---
15
net/colo-compare.c | 2 +-
12
net/colo-compare.c | 2 +-
16
1 file changed, 1 insertion(+), 1 deletion(-)
13
1 file changed, 1 insertion(+), 1 deletion(-)
17
14
18
diff --git a/net/colo-compare.c b/net/colo-compare.c
15
diff --git a/net/colo-compare.c b/net/colo-compare.c
19
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
20
--- a/net/colo-compare.c
17
--- a/net/colo-compare.c
21
+++ b/net/colo-compare.c
18
+++ b/net/colo-compare.c
22
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode, Connection **con)
19
@@ -XXX,XX +XXX,XX @@ static void colo_compare_packet(CompareState *s, Connection *conn,
23
"drop packet");
20
if (result) {
24
}
21
colo_release_primary_pkt(s, pkt);
25
}
22
packet_destroy(result->data, NULL);
26
- con = &conn;
23
- g_queue_remove(&conn->secondary_list, result->data);
27
+ *con = conn;
24
+ g_queue_delete_link(&conn->secondary_list, result);
28
25
} else {
29
return 0;
26
/*
30
}
27
* If one packet arrive late, the secondary_list or
31
--
28
--
32
2.7.4
29
2.7.4
33
30
34
31
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
2
3
The in6_address comes after the ip6_ext_hdr_routing header,
4
not after the ip6_ext_hdr one. Fix the offset.
5
6
Cc: qemu-stable@nongnu.org
7
Reported-by: Stefano Garzarella <sgarzare@redhat.com>
8
Fixes: eb700029c78 ("net_pkt: Extend packet abstraction as required by e1000e functionality")
9
Reviewed-by: Miroslav Rezanina <mrezanin@redhat.com>
10
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
11
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
---
14
net/eth.c | 2 +-
15
1 file changed, 1 insertion(+), 1 deletion(-)
16
17
diff --git a/net/eth.c b/net/eth.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/net/eth.c
20
+++ b/net/eth.c
21
@@ -XXX,XX +XXX,XX @@ _eth_get_rss_ex_dst_addr(const struct iovec *pkt, int pkt_frags,
22
}
23
24
bytes_read = iov_to_buf(pkt, pkt_frags,
25
- rthdr_offset + sizeof(*ext_hdr),
26
+ rthdr_offset + sizeof(*rthdr),
27
dst_addr, sizeof(*dst_addr));
28
29
return bytes_read == sizeof(*dst_addr);
30
--
31
2.7.4
32
33
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
2
3
The length field is already contained in the ip6_ext_hdr structure.
4
Check it direcly in eth_parse_ipv6_hdr() before calling
5
_eth_get_rss_ex_dst_addr(), which gets a bit simplified.
6
7
Reviewed-by: Miroslav Rezanina <mrezanin@redhat.com>
8
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
9
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
---
12
net/eth.c | 14 +++++++-------
13
1 file changed, 7 insertions(+), 7 deletions(-)
14
15
diff --git a/net/eth.c b/net/eth.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/net/eth.c
18
+++ b/net/eth.c
19
@@ -XXX,XX +XXX,XX @@ _eth_get_rss_ex_dst_addr(const struct iovec *pkt, int pkt_frags,
20
{
21
struct ip6_ext_hdr_routing *rthdr = (struct ip6_ext_hdr_routing *) ext_hdr;
22
23
- if ((rthdr->rtype == 2) &&
24
- (rthdr->len == sizeof(struct in6_address) / 8) &&
25
- (rthdr->segleft == 1)) {
26
+ if ((rthdr->rtype == 2) && (rthdr->segleft == 1)) {
27
28
size_t input_size = iov_size(pkt, pkt_frags);
29
size_t bytes_read;
30
@@ -XXX,XX +XXX,XX @@ bool eth_parse_ipv6_hdr(const struct iovec *pkt, int pkt_frags,
31
}
32
33
if (curr_ext_hdr_type == IP6_ROUTING) {
34
- info->rss_ex_dst_valid =
35
- _eth_get_rss_ex_dst_addr(pkt, pkt_frags,
36
- ip6hdr_off + info->full_hdr_len,
37
- &ext_hdr, &info->rss_ex_dst);
38
+ if (ext_hdr.ip6r_len == sizeof(struct in6_address) / 8) {
39
+ info->rss_ex_dst_valid =
40
+ _eth_get_rss_ex_dst_addr(pkt, pkt_frags,
41
+ ip6hdr_off + info->full_hdr_len,
42
+ &ext_hdr, &info->rss_ex_dst);
43
+ }
44
} else if (curr_ext_hdr_type == IP6_DESTINATON) {
45
info->rss_ex_src_valid =
46
_eth_get_rss_ex_src_addr(pkt, pkt_frags,
47
--
48
2.7.4
49
50
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
2
3
Since commit ab06ec43577177a442e8 we test the vmxnet3 device in the
3
The 'offset' argument represents the offset to the ip6_ext_hdr
4
pxe-tester, too (when running "make check SPEED=slow"). This now
4
header, rename it as 'ext_hdr_offset'.
5
revealed that the code is not working there if the host is a big
6
endian machine (for example ppc64 or s390x) - "make check SPEED=slow"
7
is now failing on such hosts.
8
5
9
The vmxnet3 code lacks endianness conversions in a couple of places.
6
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
10
Interestingly, the bitfields in the structs in vmxnet3.h already tried to
7
Reviewed-by: Miroslav Rezanina <mrezanin@redhat.com>
11
take care of the *bit* endianness of the C compilers - but the code missed
8
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
to change the *byte* endianness when reading or writing the corresponding
13
structs. So the bitfields are now wrapped into unions which allow to change
14
the byte endianness during runtime with the non-bitfield member of the union.
15
With these changes, "make check SPEED=slow" now properly works on big endian
16
hosts, too.
17
18
Reported-by: David Gibson <dgibson@redhat.com>
19
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
Reviewed-by: David Gibson <dgibson@redhat.com>
21
Signed-off-by: Thomas Huth <thuth@redhat.com>
22
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
23
---
10
---
24
hw/net/vmware_utils.h | 6 ++
11
net/eth.c | 6 +++---
25
hw/net/vmxnet3.c | 46 +++++++---
12
1 file changed, 3 insertions(+), 3 deletions(-)
26
hw/net/vmxnet3.h | 230 ++++++++++++++++++++++++++++++--------------------
27
3 files changed, 181 insertions(+), 101 deletions(-)
28
13
29
diff --git a/hw/net/vmware_utils.h b/hw/net/vmware_utils.h
14
diff --git a/net/eth.c b/net/eth.c
30
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/net/vmware_utils.h
16
--- a/net/eth.c
32
+++ b/hw/net/vmware_utils.h
17
+++ b/net/eth.c
33
@@ -XXX,XX +XXX,XX @@ vmw_shmem_ld16(PCIDevice *d, hwaddr addr)
18
@@ -XXX,XX +XXX,XX @@ eth_is_ip6_extension_header_type(uint8_t hdr_type)
19
20
static bool
21
_eth_get_rss_ex_dst_addr(const struct iovec *pkt, int pkt_frags,
22
- size_t rthdr_offset,
23
+ size_t ext_hdr_offset,
24
struct ip6_ext_hdr *ext_hdr,
25
struct in6_address *dst_addr)
34
{
26
{
35
uint16_t res;
27
@@ -XXX,XX +XXX,XX @@ _eth_get_rss_ex_dst_addr(const struct iovec *pkt, int pkt_frags,
36
pci_dma_read(d, addr, &res, 2);
28
size_t input_size = iov_size(pkt, pkt_frags);
37
+ res = le16_to_cpu(res);
29
size_t bytes_read;
38
VMW_SHPRN("SHMEM load16: %" PRIx64 " (value 0x%X)", addr, res);
30
39
return res;
31
- if (input_size < rthdr_offset + sizeof(*ext_hdr)) {
40
}
32
+ if (input_size < ext_hdr_offset + sizeof(*ext_hdr)) {
41
@@ -XXX,XX +XXX,XX @@ static inline void
33
return false;
42
vmw_shmem_st16(PCIDevice *d, hwaddr addr, uint16_t value)
43
{
44
VMW_SHPRN("SHMEM store16: %" PRIx64 " (value 0x%X)", addr, value);
45
+ value = cpu_to_le16(value);
46
pci_dma_write(d, addr, &value, 2);
47
}
48
49
@@ -XXX,XX +XXX,XX @@ vmw_shmem_ld32(PCIDevice *d, hwaddr addr)
50
{
51
uint32_t res;
52
pci_dma_read(d, addr, &res, 4);
53
+ res = le32_to_cpu(res);
54
VMW_SHPRN("SHMEM load32: %" PRIx64 " (value 0x%X)", addr, res);
55
return res;
56
}
57
@@ -XXX,XX +XXX,XX @@ static inline void
58
vmw_shmem_st32(PCIDevice *d, hwaddr addr, uint32_t value)
59
{
60
VMW_SHPRN("SHMEM store32: %" PRIx64 " (value 0x%X)", addr, value);
61
+ value = cpu_to_le32(value);
62
pci_dma_write(d, addr, &value, 4);
63
}
64
65
@@ -XXX,XX +XXX,XX @@ vmw_shmem_ld64(PCIDevice *d, hwaddr addr)
66
{
67
uint64_t res;
68
pci_dma_read(d, addr, &res, 8);
69
+ res = le64_to_cpu(res);
70
VMW_SHPRN("SHMEM load64: %" PRIx64 " (value %" PRIx64 ")", addr, res);
71
return res;
72
}
73
@@ -XXX,XX +XXX,XX @@ static inline void
74
vmw_shmem_st64(PCIDevice *d, hwaddr addr, uint64_t value)
75
{
76
VMW_SHPRN("SHMEM store64: %" PRIx64 " (value %" PRIx64 ")", addr, value);
77
+ value = cpu_to_le64(value);
78
pci_dma_write(d, addr, &value, 8);
79
}
80
81
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
82
index XXXXXXX..XXXXXXX 100644
83
--- a/hw/net/vmxnet3.c
84
+++ b/hw/net/vmxnet3.c
85
@@ -XXX,XX +XXX,XX @@ vmxnet3_dump_tx_descr(struct Vmxnet3_TxDesc *descr)
86
"addr %" PRIx64 ", len: %d, gen: %d, rsvd: %d, "
87
"dtype: %d, ext1: %d, msscof: %d, hlen: %d, om: %d, "
88
"eop: %d, cq: %d, ext2: %d, ti: %d, tci: %d",
89
- le64_to_cpu(descr->addr), descr->len, descr->gen, descr->rsvd,
90
+ descr->addr, descr->len, descr->gen, descr->rsvd,
91
descr->dtype, descr->ext1, descr->msscof, descr->hlen, descr->om,
92
descr->eop, descr->cq, descr->ext2, descr->ti, descr->tci);
93
}
94
@@ -XXX,XX +XXX,XX @@ vmxnet3_dump_rx_descr(struct Vmxnet3_RxDesc *descr)
95
{
96
VMW_PKPRN("RX DESCR: addr %" PRIx64 ", len: %d, gen: %d, rsvd: %d, "
97
"dtype: %d, ext1: %d, btype: %d",
98
- le64_to_cpu(descr->addr), descr->len, descr->gen,
99
+ descr->addr, descr->len, descr->gen,
100
descr->rsvd, descr->dtype, descr->ext1, descr->btype);
101
}
102
103
@@ -XXX,XX +XXX,XX @@ static void vmxnet3_complete_packet(VMXNET3State *s, int qidx, uint32_t tx_ridx)
104
memset(&txcq_descr, 0, sizeof(txcq_descr));
105
txcq_descr.txdIdx = tx_ridx;
106
txcq_descr.gen = vmxnet3_ring_curr_gen(&s->txq_descr[qidx].comp_ring);
107
-
108
+ txcq_descr.val1 = cpu_to_le32(txcq_descr.val1);
109
+ txcq_descr.val2 = cpu_to_le32(txcq_descr.val2);
110
vmxnet3_ring_write_curr_cell(d, &s->txq_descr[qidx].comp_ring, &txcq_descr);
111
112
/* Flush changes in TX descriptor before changing the counter value */
113
@@ -XXX,XX +XXX,XX @@ vmxnet3_on_rx_done_update_stats(VMXNET3State *s,
114
}
115
}
116
117
+static inline void
118
+vmxnet3_ring_read_curr_txdesc(PCIDevice *pcidev, Vmxnet3Ring *ring,
119
+ struct Vmxnet3_TxDesc *txd)
120
+{
121
+ vmxnet3_ring_read_curr_cell(pcidev, ring, txd);
122
+ txd->addr = le64_to_cpu(txd->addr);
123
+ txd->val1 = le32_to_cpu(txd->val1);
124
+ txd->val2 = le32_to_cpu(txd->val2);
125
+}
126
+
127
static inline bool
128
vmxnet3_pop_next_tx_descr(VMXNET3State *s,
129
int qidx,
130
@@ -XXX,XX +XXX,XX @@ vmxnet3_pop_next_tx_descr(VMXNET3State *s,
131
Vmxnet3Ring *ring = &s->txq_descr[qidx].tx_ring;
132
PCIDevice *d = PCI_DEVICE(s);
133
134
- vmxnet3_ring_read_curr_cell(d, ring, txd);
135
+ vmxnet3_ring_read_curr_txdesc(d, ring, txd);
136
if (txd->gen == vmxnet3_ring_curr_gen(ring)) {
137
/* Only read after generation field verification */
138
smp_rmb();
139
/* Re-read to be sure we got the latest version */
140
- vmxnet3_ring_read_curr_cell(d, ring, txd);
141
+ vmxnet3_ring_read_curr_txdesc(d, ring, txd);
142
VMXNET3_RING_DUMP(VMW_RIPRN, "TX", qidx, ring);
143
*descr_idx = vmxnet3_ring_curr_cell_idx(ring);
144
vmxnet3_inc_tx_consumption_counter(s, qidx);
145
@@ -XXX,XX +XXX,XX @@ static void vmxnet3_process_tx_queue(VMXNET3State *s, int qidx)
146
147
if (!s->skip_current_tx_pkt) {
148
data_len = (txd.len > 0) ? txd.len : VMXNET3_MAX_TX_BUF_SIZE;
149
- data_pa = le64_to_cpu(txd.addr);
150
+ data_pa = txd.addr;
151
152
if (!net_tx_pkt_add_raw_fragment(s->tx_pkt,
153
data_pa,
154
@@ -XXX,XX +XXX,XX @@ vmxnet3_read_next_rx_descr(VMXNET3State *s, int qidx, int ridx,
155
Vmxnet3Ring *ring = &s->rxq_descr[qidx].rx_ring[ridx];
156
*didx = vmxnet3_ring_curr_cell_idx(ring);
157
vmxnet3_ring_read_curr_cell(d, ring, dbuf);
158
+ dbuf->addr = le64_to_cpu(dbuf->addr);
159
+ dbuf->val1 = le32_to_cpu(dbuf->val1);
160
+ dbuf->ext1 = le32_to_cpu(dbuf->ext1);
161
}
162
163
static inline uint8_t
164
@@ -XXX,XX +XXX,XX @@ vmxnet3_pop_rxc_descr(VMXNET3State *s, int qidx, uint32_t *descr_gen)
165
166
pci_dma_read(PCI_DEVICE(s),
167
daddr, &rxcd, sizeof(struct Vmxnet3_RxCompDesc));
168
+ rxcd.val1 = le32_to_cpu(rxcd.val1);
169
+ rxcd.val2 = le32_to_cpu(rxcd.val2);
170
+ rxcd.val3 = le32_to_cpu(rxcd.val3);
171
ring_gen = vmxnet3_ring_curr_gen(&s->rxq_descr[qidx].comp_ring);
172
173
if (rxcd.gen != ring_gen) {
174
@@ -XXX,XX +XXX,XX @@ vmxnet3_pci_dma_writev(PCIDevice *pci_dev,
175
}
176
}
177
178
+static void
179
+vmxnet3_pci_dma_write_rxcd(PCIDevice *pcidev, dma_addr_t pa,
180
+ struct Vmxnet3_RxCompDesc *rxcd)
181
+{
182
+ rxcd->val1 = cpu_to_le32(rxcd->val1);
183
+ rxcd->val2 = cpu_to_le32(rxcd->val2);
184
+ rxcd->val3 = cpu_to_le32(rxcd->val3);
185
+ pci_dma_write(pcidev, pa, rxcd, sizeof(*rxcd));
186
+}
187
+
188
static bool
189
vmxnet3_indicate_packet(VMXNET3State *s)
190
{
191
@@ -XXX,XX +XXX,XX @@ vmxnet3_indicate_packet(VMXNET3State *s)
192
}
34
}
193
35
194
chunk_size = MIN(bytes_left, rxd.len);
36
bytes_read = iov_to_buf(pkt, pkt_frags,
195
- vmxnet3_pci_dma_writev(d, data, bytes_copied,
37
- rthdr_offset + sizeof(*rthdr),
196
- le64_to_cpu(rxd.addr), chunk_size);
38
+ ext_hdr_offset + sizeof(*rthdr),
197
+ vmxnet3_pci_dma_writev(d, data, bytes_copied, rxd.addr, chunk_size);
39
dst_addr, sizeof(*dst_addr));
198
bytes_copied += chunk_size;
40
199
bytes_left -= chunk_size;
41
return bytes_read == sizeof(*dst_addr);
200
201
vmxnet3_dump_rx_descr(&rxd);
202
203
if (ready_rxcd_pa != 0) {
204
- pci_dma_write(d, ready_rxcd_pa, &rxcd, sizeof(rxcd));
205
+ vmxnet3_pci_dma_write_rxcd(d, ready_rxcd_pa, &rxcd);
206
}
207
208
memset(&rxcd, 0, sizeof(struct Vmxnet3_RxCompDesc));
209
@@ -XXX,XX +XXX,XX @@ vmxnet3_indicate_packet(VMXNET3State *s)
210
rxcd.eop = 1;
211
rxcd.err = (bytes_left != 0);
212
213
- pci_dma_write(d, ready_rxcd_pa, &rxcd, sizeof(rxcd));
214
+ vmxnet3_pci_dma_write_rxcd(d, ready_rxcd_pa, &rxcd);
215
216
/* Flush RX descriptor changes */
217
smp_wmb();
218
diff --git a/hw/net/vmxnet3.h b/hw/net/vmxnet3.h
219
index XXXXXXX..XXXXXXX 100644
220
--- a/hw/net/vmxnet3.h
221
+++ b/hw/net/vmxnet3.h
222
@@ -XXX,XX +XXX,XX @@ enum {
223
struct Vmxnet3_TxDesc {
224
__le64 addr;
225
226
+ union {
227
+ struct {
228
#ifdef __BIG_ENDIAN_BITFIELD
229
- u32 msscof:14; /* MSS, checksum offset, flags */
230
- u32 ext1:1;
231
- u32 dtype:1; /* descriptor type */
232
- u32 rsvd:1;
233
- u32 gen:1; /* generation bit */
234
- u32 len:14;
235
+ u32 msscof:14; /* MSS, checksum offset, flags */
236
+ u32 ext1:1;
237
+ u32 dtype:1; /* descriptor type */
238
+ u32 rsvd:1;
239
+ u32 gen:1; /* generation bit */
240
+ u32 len:14;
241
#else
242
- u32 len:14;
243
- u32 gen:1; /* generation bit */
244
- u32 rsvd:1;
245
- u32 dtype:1; /* descriptor type */
246
- u32 ext1:1;
247
- u32 msscof:14; /* MSS, checksum offset, flags */
248
+ u32 len:14;
249
+ u32 gen:1; /* generation bit */
250
+ u32 rsvd:1;
251
+ u32 dtype:1; /* descriptor type */
252
+ u32 ext1:1;
253
+ u32 msscof:14; /* MSS, checksum offset, flags */
254
#endif /* __BIG_ENDIAN_BITFIELD */
255
-
256
+ };
257
+ u32 val1;
258
+ };
259
+
260
+ union {
261
+ struct {
262
#ifdef __BIG_ENDIAN_BITFIELD
263
- u32 tci:16; /* Tag to Insert */
264
- u32 ti:1; /* VLAN Tag Insertion */
265
- u32 ext2:1;
266
- u32 cq:1; /* completion request */
267
- u32 eop:1; /* End Of Packet */
268
- u32 om:2; /* offload mode */
269
- u32 hlen:10; /* header len */
270
+ u32 tci:16; /* Tag to Insert */
271
+ u32 ti:1; /* VLAN Tag Insertion */
272
+ u32 ext2:1;
273
+ u32 cq:1; /* completion request */
274
+ u32 eop:1; /* End Of Packet */
275
+ u32 om:2; /* offload mode */
276
+ u32 hlen:10; /* header len */
277
#else
278
- u32 hlen:10; /* header len */
279
- u32 om:2; /* offload mode */
280
- u32 eop:1; /* End Of Packet */
281
- u32 cq:1; /* completion request */
282
- u32 ext2:1;
283
- u32 ti:1; /* VLAN Tag Insertion */
284
- u32 tci:16; /* Tag to Insert */
285
+ u32 hlen:10; /* header len */
286
+ u32 om:2; /* offload mode */
287
+ u32 eop:1; /* End Of Packet */
288
+ u32 cq:1; /* completion request */
289
+ u32 ext2:1;
290
+ u32 ti:1; /* VLAN Tag Insertion */
291
+ u32 tci:16; /* Tag to Insert */
292
#endif /* __BIG_ENDIAN_BITFIELD */
293
+ };
294
+ u32 val2;
295
+ };
296
};
297
298
/* TxDesc.OM values */
299
@@ -XXX,XX +XXX,XX @@ struct Vmxnet3_TxDataDesc {
300
#define VMXNET3_TCD_GEN_DWORD_SHIFT 3
301
302
struct Vmxnet3_TxCompDesc {
303
- u32 txdIdx:12; /* Index of the EOP TxDesc */
304
- u32 ext1:20;
305
-
306
+ union {
307
+ struct {
308
+#ifdef __BIG_ENDIAN_BITFIELD
309
+ u32 ext1:20;
310
+ u32 txdIdx:12; /* Index of the EOP TxDesc */
311
+#else
312
+ u32 txdIdx:12; /* Index of the EOP TxDesc */
313
+ u32 ext1:20;
314
+#endif
315
+ };
316
+ u32 val1;
317
+ };
318
__le32 ext2;
319
__le32 ext3;
320
321
- u32 rsvd:24;
322
- u32 type:7; /* completion type */
323
- u32 gen:1; /* generation bit */
324
+ union {
325
+ struct {
326
+#ifdef __BIG_ENDIAN_BITFIELD
327
+ u32 gen:1; /* generation bit */
328
+ u32 type:7; /* completion type */
329
+ u32 rsvd:24;
330
+#else
331
+ u32 rsvd:24;
332
+ u32 type:7; /* completion type */
333
+ u32 gen:1; /* generation bit */
334
+#endif
335
+ };
336
+ u32 val2;
337
+ };
338
};
339
340
struct Vmxnet3_RxDesc {
341
__le64 addr;
342
-
343
+ union {
344
+ struct {
345
#ifdef __BIG_ENDIAN_BITFIELD
346
- u32 gen:1; /* Generation bit */
347
- u32 rsvd:15;
348
- u32 dtype:1; /* Descriptor type */
349
- u32 btype:1; /* Buffer Type */
350
- u32 len:14;
351
+ u32 gen:1; /* Generation bit */
352
+ u32 rsvd:15;
353
+ u32 dtype:1; /* Descriptor type */
354
+ u32 btype:1; /* Buffer Type */
355
+ u32 len:14;
356
#else
357
- u32 len:14;
358
- u32 btype:1; /* Buffer Type */
359
- u32 dtype:1; /* Descriptor type */
360
- u32 rsvd:15;
361
- u32 gen:1; /* Generation bit */
362
+ u32 len:14;
363
+ u32 btype:1; /* Buffer Type */
364
+ u32 dtype:1; /* Descriptor type */
365
+ u32 rsvd:15;
366
+ u32 gen:1; /* Generation bit */
367
#endif
368
+ };
369
+ u32 val1;
370
+ };
371
u32 ext1;
372
};
373
374
@@ -XXX,XX +XXX,XX @@ struct Vmxnet3_RxDesc {
375
#define VMXNET3_RXD_GEN_SHIFT 31
376
377
struct Vmxnet3_RxCompDesc {
378
+ union {
379
+ struct {
380
#ifdef __BIG_ENDIAN_BITFIELD
381
- u32 ext2:1;
382
- u32 cnc:1; /* Checksum Not Calculated */
383
- u32 rssType:4; /* RSS hash type used */
384
- u32 rqID:10; /* rx queue/ring ID */
385
- u32 sop:1; /* Start of Packet */
386
- u32 eop:1; /* End of Packet */
387
- u32 ext1:2;
388
- u32 rxdIdx:12; /* Index of the RxDesc */
389
+ u32 ext2:1;
390
+ u32 cnc:1; /* Checksum Not Calculated */
391
+ u32 rssType:4; /* RSS hash type used */
392
+ u32 rqID:10; /* rx queue/ring ID */
393
+ u32 sop:1; /* Start of Packet */
394
+ u32 eop:1; /* End of Packet */
395
+ u32 ext1:2;
396
+ u32 rxdIdx:12; /* Index of the RxDesc */
397
#else
398
- u32 rxdIdx:12; /* Index of the RxDesc */
399
- u32 ext1:2;
400
- u32 eop:1; /* End of Packet */
401
- u32 sop:1; /* Start of Packet */
402
- u32 rqID:10; /* rx queue/ring ID */
403
- u32 rssType:4; /* RSS hash type used */
404
- u32 cnc:1; /* Checksum Not Calculated */
405
- u32 ext2:1;
406
+ u32 rxdIdx:12; /* Index of the RxDesc */
407
+ u32 ext1:2;
408
+ u32 eop:1; /* End of Packet */
409
+ u32 sop:1; /* Start of Packet */
410
+ u32 rqID:10; /* rx queue/ring ID */
411
+ u32 rssType:4; /* RSS hash type used */
412
+ u32 cnc:1; /* Checksum Not Calculated */
413
+ u32 ext2:1;
414
#endif /* __BIG_ENDIAN_BITFIELD */
415
+ };
416
+ u32 val1;
417
+ };
418
419
__le32 rssHash; /* RSS hash value */
420
421
+ union {
422
+ struct {
423
#ifdef __BIG_ENDIAN_BITFIELD
424
- u32 tci:16; /* Tag stripped */
425
- u32 ts:1; /* Tag is stripped */
426
- u32 err:1; /* Error */
427
- u32 len:14; /* data length */
428
+ u32 tci:16; /* Tag stripped */
429
+ u32 ts:1; /* Tag is stripped */
430
+ u32 err:1; /* Error */
431
+ u32 len:14; /* data length */
432
#else
433
- u32 len:14; /* data length */
434
- u32 err:1; /* Error */
435
- u32 ts:1; /* Tag is stripped */
436
- u32 tci:16; /* Tag stripped */
437
+ u32 len:14; /* data length */
438
+ u32 err:1; /* Error */
439
+ u32 ts:1; /* Tag is stripped */
440
+ u32 tci:16; /* Tag stripped */
441
#endif /* __BIG_ENDIAN_BITFIELD */
442
+ };
443
+ u32 val2;
444
+ };
445
446
-
447
+ union {
448
+ struct {
449
#ifdef __BIG_ENDIAN_BITFIELD
450
- u32 gen:1; /* generation bit */
451
- u32 type:7; /* completion type */
452
- u32 fcs:1; /* Frame CRC correct */
453
- u32 frg:1; /* IP Fragment */
454
- u32 v4:1; /* IPv4 */
455
- u32 v6:1; /* IPv6 */
456
- u32 ipc:1; /* IP Checksum Correct */
457
- u32 tcp:1; /* TCP packet */
458
- u32 udp:1; /* UDP packet */
459
- u32 tuc:1; /* TCP/UDP Checksum Correct */
460
- u32 csum:16;
461
+ u32 gen:1; /* generation bit */
462
+ u32 type:7; /* completion type */
463
+ u32 fcs:1; /* Frame CRC correct */
464
+ u32 frg:1; /* IP Fragment */
465
+ u32 v4:1; /* IPv4 */
466
+ u32 v6:1; /* IPv6 */
467
+ u32 ipc:1; /* IP Checksum Correct */
468
+ u32 tcp:1; /* TCP packet */
469
+ u32 udp:1; /* UDP packet */
470
+ u32 tuc:1; /* TCP/UDP Checksum Correct */
471
+ u32 csum:16;
472
#else
473
- u32 csum:16;
474
- u32 tuc:1; /* TCP/UDP Checksum Correct */
475
- u32 udp:1; /* UDP packet */
476
- u32 tcp:1; /* TCP packet */
477
- u32 ipc:1; /* IP Checksum Correct */
478
- u32 v6:1; /* IPv6 */
479
- u32 v4:1; /* IPv4 */
480
- u32 frg:1; /* IP Fragment */
481
- u32 fcs:1; /* Frame CRC correct */
482
- u32 type:7; /* completion type */
483
- u32 gen:1; /* generation bit */
484
+ u32 csum:16;
485
+ u32 tuc:1; /* TCP/UDP Checksum Correct */
486
+ u32 udp:1; /* UDP packet */
487
+ u32 tcp:1; /* TCP packet */
488
+ u32 ipc:1; /* IP Checksum Correct */
489
+ u32 v6:1; /* IPv6 */
490
+ u32 v4:1; /* IPv4 */
491
+ u32 frg:1; /* IP Fragment */
492
+ u32 fcs:1; /* Frame CRC correct */
493
+ u32 type:7; /* completion type */
494
+ u32 gen:1; /* generation bit */
495
#endif /* __BIG_ENDIAN_BITFIELD */
496
+ };
497
+ u32 val3;
498
+ };
499
};
500
501
/* fields in RxCompDesc we access via Vmxnet3_GenericDesc.dword[3] */
502
--
42
--
503
2.7.4
43
2.7.4
504
44
505
45
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
2
3
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
4
Reviewed-by: Miroslav Rezanina <mrezanin@redhat.com>
5
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
---
8
net/eth.c | 14 ++++++--------
9
1 file changed, 6 insertions(+), 8 deletions(-)
10
11
diff --git a/net/eth.c b/net/eth.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/net/eth.c
14
+++ b/net/eth.c
15
@@ -XXX,XX +XXX,XX @@ _eth_get_rss_ex_dst_addr(const struct iovec *pkt, int pkt_frags,
16
struct in6_address *dst_addr)
17
{
18
struct ip6_ext_hdr_routing *rthdr = (struct ip6_ext_hdr_routing *) ext_hdr;
19
+ size_t input_size = iov_size(pkt, pkt_frags);
20
+ size_t bytes_read;
21
22
- if ((rthdr->rtype == 2) && (rthdr->segleft == 1)) {
23
-
24
- size_t input_size = iov_size(pkt, pkt_frags);
25
- size_t bytes_read;
26
-
27
- if (input_size < ext_hdr_offset + sizeof(*ext_hdr)) {
28
- return false;
29
- }
30
+ if (input_size < ext_hdr_offset + sizeof(*ext_hdr)) {
31
+ return false;
32
+ }
33
34
+ if ((rthdr->rtype == 2) && (rthdr->segleft == 1)) {
35
bytes_read = iov_to_buf(pkt, pkt_frags,
36
ext_hdr_offset + sizeof(*rthdr),
37
dst_addr, sizeof(*dst_addr));
38
--
39
2.7.4
40
41
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
2
3
Since commit 1865e288a823c764cd4344d ("Fix eepro100 simple transmission
3
We want to check fields from ip6_ext_hdr_routing structure
4
mode"), the test/pxe-test is broken for the eepro100 device on big
4
and if correct read the full in6_address. Let's directly check
5
endian hosts. However, it seems like that commit did not introduce the
5
if our iovec contains enough data for everything, else return
6
problem, but just uncovered it: The EEPRO100State->tx.tbd_array_addr and
6
early.
7
EEPRO100State->tx.tcb_bytes fields are already in host byte order, since
8
they have already been byte-swapped in the read_cb() function.
9
Thus byte-swapping them in tx_command() again results in the wrong
10
endianness. Removing the byte-swapping here fixes the pxe-test.
11
7
12
Signed-off-by: Thomas Huth <thuth@redhat.com>
8
Suggested-by: Stefano Garzarella <sgarzare@redhat.com>
9
Reviewed-by: Miroslav Rezanina <mrezanin@redhat.com>
10
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
13
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
14
---
12
---
15
hw/net/eepro100.c | 4 ++--
13
net/eth.c | 2 +-
16
1 file changed, 2 insertions(+), 2 deletions(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
17
15
18
diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
16
diff --git a/net/eth.c b/net/eth.c
19
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/net/eepro100.c
18
--- a/net/eth.c
21
+++ b/hw/net/eepro100.c
19
+++ b/net/eth.c
22
@@ -XXX,XX +XXX,XX @@ static void read_cb(EEPRO100State *s)
20
@@ -XXX,XX +XXX,XX @@ _eth_get_rss_ex_dst_addr(const struct iovec *pkt, int pkt_frags,
23
21
size_t input_size = iov_size(pkt, pkt_frags);
24
static void tx_command(EEPRO100State *s)
22
size_t bytes_read;
25
{
23
26
- uint32_t tbd_array = le32_to_cpu(s->tx.tbd_array_addr);
24
- if (input_size < ext_hdr_offset + sizeof(*ext_hdr)) {
27
- uint16_t tcb_bytes = (le16_to_cpu(s->tx.tcb_bytes) & 0x3fff);
25
+ if (input_size < ext_hdr_offset + sizeof(*rthdr) + sizeof(*dst_addr)) {
28
+ uint32_t tbd_array = s->tx.tbd_array_addr;
26
return false;
29
+ uint16_t tcb_bytes = s->tx.tcb_bytes & 0x3fff;
27
}
30
/* Sends larger than MAX_ETH_FRAME_SIZE are allowed, up to 2600 bytes. */
28
31
uint8_t buf[2600];
32
uint16_t size = 0;
33
--
29
--
34
2.7.4
30
2.7.4
35
31
36
32
diff view generated by jsdifflib
1
From: Stefan Weil <sw@weilnetz.de>
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
2
3
Signed-off-by: Stefan Weil <sw@weilnetz.de>
3
We can't know the caller read enough data in the memory pointed
4
by ext_hdr to cast it as a ip6_ext_hdr_routing.
5
Declare rt_hdr on the stack and fill it again from the iovec.
6
7
Since we already checked there is enough data in the iovec buffer,
8
simply add an assert() call to consume the bytes_read variable.
9
10
This fix a 2 bytes buffer overrun in eth_parse_ipv6_hdr() reported
11
by QEMU fuzzer:
12
13
$ cat << EOF | ./qemu-system-i386 -M pc-q35-5.0 \
14
-accel qtest -monitor none \
15
-serial none -nographic -qtest stdio
16
outl 0xcf8 0x80001010
17
outl 0xcfc 0xe1020000
18
outl 0xcf8 0x80001004
19
outw 0xcfc 0x7
20
write 0x25 0x1 0x86
21
write 0x26 0x1 0xdd
22
write 0x4f 0x1 0x2b
23
write 0xe1020030 0x4 0x190002e1
24
write 0xe102003a 0x2 0x0807
25
write 0xe1020048 0x4 0x12077cdd
26
write 0xe1020400 0x4 0xba077cdd
27
write 0xe1020420 0x4 0x190002e1
28
write 0xe1020428 0x4 0x3509d807
29
write 0xe1020438 0x1 0xe2
30
EOF
31
=================================================================
32
==2859770==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffdef904902 at pc 0x561ceefa78de bp 0x7ffdef904820 sp 0x7ffdef904818
33
READ of size 1 at 0x7ffdef904902 thread T0
34
#0 0x561ceefa78dd in _eth_get_rss_ex_dst_addr net/eth.c:410:17
35
#1 0x561ceefa41fb in eth_parse_ipv6_hdr net/eth.c:532:17
36
#2 0x561cef7de639 in net_tx_pkt_parse_headers hw/net/net_tx_pkt.c:228:14
37
#3 0x561cef7dbef4 in net_tx_pkt_parse hw/net/net_tx_pkt.c:273:9
38
#4 0x561ceec29f22 in e1000e_process_tx_desc hw/net/e1000e_core.c:730:29
39
#5 0x561ceec28eac in e1000e_start_xmit hw/net/e1000e_core.c:927:9
40
#6 0x561ceec1baab in e1000e_set_tdt hw/net/e1000e_core.c:2444:9
41
#7 0x561ceebf300e in e1000e_core_write hw/net/e1000e_core.c:3256:9
42
#8 0x561cef3cd4cd in e1000e_mmio_write hw/net/e1000e.c:110:5
43
44
Address 0x7ffdef904902 is located in stack of thread T0 at offset 34 in frame
45
#0 0x561ceefa320f in eth_parse_ipv6_hdr net/eth.c:486
46
47
This frame has 1 object(s):
48
[32, 34) 'ext_hdr' (line 487) <== Memory access at offset 34 overflows this variable
49
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
50
(longjmp and C++ exceptions *are* supported)
51
SUMMARY: AddressSanitizer: stack-buffer-overflow net/eth.c:410:17 in _eth_get_rss_ex_dst_addr
52
Shadow bytes around the buggy address:
53
0x10003df188d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
54
0x10003df188e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
55
0x10003df188f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
56
0x10003df18900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
57
0x10003df18910: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
58
=>0x10003df18920:[02]f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
59
0x10003df18930: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
60
0x10003df18940: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
61
0x10003df18950: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
62
0x10003df18960: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
63
0x10003df18970: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
64
Shadow byte legend (one shadow byte represents 8 application bytes):
65
Addressable: 00
66
Partially addressable: 01 02 03 04 05 06 07
67
Stack left redzone: f1
68
Stack right redzone: f3
69
==2859770==ABORTING
70
71
Add the corresponding qtest case with the fuzzer reproducer.
72
73
FWIW GCC 11 similarly reported:
74
75
net/eth.c: In function 'eth_parse_ipv6_hdr':
76
net/eth.c:410:15: error: array subscript 'struct ip6_ext_hdr_routing[0]' is partly outside array bounds of 'struct ip6_ext_hdr[1]' [-Werror=array-bounds]
77
410 | if ((rthdr->rtype == 2) && (rthdr->segleft == 1)) {
78
| ~~~~~^~~~~~~
79
net/eth.c:485:24: note: while referencing 'ext_hdr'
80
485 | struct ip6_ext_hdr ext_hdr;
81
| ^~~~~~~
82
net/eth.c:410:38: error: array subscript 'struct ip6_ext_hdr_routing[0]' is partly outside array bounds of 'struct ip6_ext_hdr[1]' [-Werror=array-bounds]
83
410 | if ((rthdr->rtype == 2) && (rthdr->segleft == 1)) {
84
| ~~~~~^~~~~~~~~
85
net/eth.c:485:24: note: while referencing 'ext_hdr'
86
485 | struct ip6_ext_hdr ext_hdr;
87
| ^~~~~~~
88
89
Cc: qemu-stable@nongnu.org
90
Buglink: https://bugs.launchpad.net/qemu/+bug/1879531
91
Reported-by: Alexander Bulekov <alxndr@bu.edu>
92
Reported-by: Miroslav Rezanina <mrezanin@redhat.com>
93
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
94
Reviewed-by: Miroslav Rezanina <mrezanin@redhat.com>
95
Fixes: eb700029c78 ("net_pkt: Extend packet abstraction as required by e1000e functionality")
96
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
4
Signed-off-by: Jason Wang <jasowang@redhat.com>
97
Signed-off-by: Jason Wang <jasowang@redhat.com>
5
---
98
---
6
MAINTAINERS | 5 +++++
99
MAINTAINERS | 1 +
7
1 file changed, 5 insertions(+)
100
net/eth.c | 13 +++++++----
101
tests/qtest/fuzz-e1000e-test.c | 53 ++++++++++++++++++++++++++++++++++++++++++
102
tests/qtest/meson.build | 1 +
103
4 files changed, 63 insertions(+), 5 deletions(-)
104
create mode 100644 tests/qtest/fuzz-e1000e-test.c
8
105
9
diff --git a/MAINTAINERS b/MAINTAINERS
106
diff --git a/MAINTAINERS b/MAINTAINERS
10
index XXXXXXX..XXXXXXX 100644
107
index XXXXXXX..XXXXXXX 100644
11
--- a/MAINTAINERS
108
--- a/MAINTAINERS
12
+++ b/MAINTAINERS
109
+++ b/MAINTAINERS
13
@@ -XXX,XX +XXX,XX @@ M: Dmitry Fleytman <dmitry@daynix.com>
110
@@ -XXX,XX +XXX,XX @@ e1000e
111
M: Dmitry Fleytman <dmitry.fleytman@gmail.com>
14
S: Maintained
112
S: Maintained
15
F: hw/net/e1000e*
113
F: hw/net/e1000e*
16
114
+F: tests/qtest/fuzz-e1000e-test.c
17
+eepro100
115
18
+M: Stefan Weil <sw@weilnetz.de>
116
eepro100
19
+S: Maintained
117
M: Stefan Weil <sw@weilnetz.de>
20
+F: hw/net/eepro100.c
118
diff --git a/net/eth.c b/net/eth.c
21
+
119
index XXXXXXX..XXXXXXX 100644
22
Generic Loader
120
--- a/net/eth.c
23
M: Alistair Francis <alistair.francis@xilinx.com>
121
+++ b/net/eth.c
24
S: Maintained
122
@@ -XXX,XX +XXX,XX @@ _eth_get_rss_ex_dst_addr(const struct iovec *pkt, int pkt_frags,
123
struct ip6_ext_hdr *ext_hdr,
124
struct in6_address *dst_addr)
125
{
126
- struct ip6_ext_hdr_routing *rthdr = (struct ip6_ext_hdr_routing *) ext_hdr;
127
+ struct ip6_ext_hdr_routing rt_hdr;
128
size_t input_size = iov_size(pkt, pkt_frags);
129
size_t bytes_read;
130
131
- if (input_size < ext_hdr_offset + sizeof(*rthdr) + sizeof(*dst_addr)) {
132
+ if (input_size < ext_hdr_offset + sizeof(rt_hdr) + sizeof(*dst_addr)) {
133
return false;
134
}
135
136
- if ((rthdr->rtype == 2) && (rthdr->segleft == 1)) {
137
- bytes_read = iov_to_buf(pkt, pkt_frags,
138
- ext_hdr_offset + sizeof(*rthdr),
139
+ bytes_read = iov_to_buf(pkt, pkt_frags, ext_hdr_offset,
140
+ &rt_hdr, sizeof(rt_hdr));
141
+ assert(bytes_read == sizeof(rt_hdr));
142
+
143
+ if ((rt_hdr.rtype == 2) && (rt_hdr.segleft == 1)) {
144
+ bytes_read = iov_to_buf(pkt, pkt_frags, ext_hdr_offset + sizeof(rt_hdr),
145
dst_addr, sizeof(*dst_addr));
146
147
return bytes_read == sizeof(*dst_addr);
148
diff --git a/tests/qtest/fuzz-e1000e-test.c b/tests/qtest/fuzz-e1000e-test.c
149
new file mode 100644
150
index XXXXXXX..XXXXXXX
151
--- /dev/null
152
+++ b/tests/qtest/fuzz-e1000e-test.c
153
@@ -XXX,XX +XXX,XX @@
154
+/*
155
+ * QTest testcase for e1000e device generated by fuzzer
156
+ *
157
+ * Copyright (c) 2021 Red Hat, Inc.
158
+ *
159
+ * SPDX-License-Identifier: GPL-2.0-or-later
160
+ */
161
+
162
+#include "qemu/osdep.h"
163
+
164
+#include "libqos/libqtest.h"
165
+
166
+/*
167
+ * https://bugs.launchpad.net/qemu/+bug/1879531
168
+ */
169
+static void test_lp1879531_eth_get_rss_ex_dst_addr(void)
170
+{
171
+ QTestState *s;
172
+
173
+ s = qtest_init("-nographic -monitor none -serial none -M pc-q35-5.0");
174
+
175
+ qtest_outl(s, 0xcf8, 0x80001010);
176
+ qtest_outl(s, 0xcfc, 0xe1020000);
177
+ qtest_outl(s, 0xcf8, 0x80001004);
178
+ qtest_outw(s, 0xcfc, 0x7);
179
+ qtest_writeb(s, 0x25, 0x86);
180
+ qtest_writeb(s, 0x26, 0xdd);
181
+ qtest_writeb(s, 0x4f, 0x2b);
182
+
183
+ qtest_writel(s, 0xe1020030, 0x190002e1);
184
+ qtest_writew(s, 0xe102003a, 0x0807);
185
+ qtest_writel(s, 0xe1020048, 0x12077cdd);
186
+ qtest_writel(s, 0xe1020400, 0xba077cdd);
187
+ qtest_writel(s, 0xe1020420, 0x190002e1);
188
+ qtest_writel(s, 0xe1020428, 0x3509d807);
189
+ qtest_writeb(s, 0xe1020438, 0xe2);
190
+ qtest_writeb(s, 0x4f, 0x2b);
191
+ qtest_quit(s);
192
+}
193
+
194
+int main(int argc, char **argv)
195
+{
196
+ const char *arch = qtest_get_arch();
197
+
198
+ g_test_init(&argc, &argv, NULL);
199
+
200
+ if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
201
+ qtest_add_func("fuzz/test_lp1879531_eth_get_rss_ex_dst_addr",
202
+ test_lp1879531_eth_get_rss_ex_dst_addr);
203
+ }
204
+
205
+ return g_test_run();
206
+}
207
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
208
index XXXXXXX..XXXXXXX 100644
209
--- a/tests/qtest/meson.build
210
+++ b/tests/qtest/meson.build
211
@@ -XXX,XX +XXX,XX @@ qtests_i386 = \
212
(config_all_devices.has_key('CONFIG_TPM_TIS_ISA') ? ['tpm-tis-test'] : []) + \
213
(config_all_devices.has_key('CONFIG_TPM_TIS_ISA') ? ['tpm-tis-swtpm-test'] : []) + \
214
(config_all_devices.has_key('CONFIG_RTL8139_PCI') ? ['rtl8139-test'] : []) + \
215
+ (config_all_devices.has_key('CONFIG_E1000E_PCI_EXPRESS') ? ['fuzz-e1000e-test'] : []) + \
216
qtests_pci + \
217
['fdc-test',
218
'ide-test',
25
--
219
--
26
2.7.4
220
2.7.4
27
221
28
222
diff view generated by jsdifflib
1
From: Ed Swierk <eswierk@skyportsystems.com>
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
2
3
The checksum algorithm used by IPv4, TCP and UDP allows a zero value
3
To simplify the function body, invert the if() statement, returning
4
to be represented by either 0x0000 and 0xFFFF. But per RFC 768, a zero
4
earlier.
5
UDP checksum must be transmitted as 0xFFFF because 0x0000 is a special
5
Since we already checked there is enough data in the iovec buffer,
6
value meaning no checksum.
6
simply add an assert() call to consume the bytes_read variable.
7
7
8
Substitute 0xFFFF whenever a checksum is computed as zero when
8
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
9
modifying a UDP datagram header. Doing this on IPv4 and TCP checksums
9
Reviewed-by: Miroslav Rezanina <mrezanin@redhat.com>
10
is unnecessary but legal. Add a wrapper for net_checksum_finish() that
10
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
makes the substitution.
12
13
(We can't just change net_checksum_finish(), as that function is also
14
used by receivers to verify checksums, and in that case the expected
15
value is always 0x0000.)
16
17
Signed-off-by: Ed Swierk <eswierk@skyportsystems.com>
18
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
19
---
12
---
20
hw/net/e1000.c | 2 +-
13
net/eth.c | 13 ++++++-------
21
hw/net/net_rx_pkt.c | 2 +-
14
1 file changed, 6 insertions(+), 7 deletions(-)
22
hw/net/net_tx_pkt.c | 2 +-
23
hw/net/vmxnet3.c | 3 ++-
24
include/net/checksum.h | 6 ++++++
25
5 files changed, 11 insertions(+), 4 deletions(-)
26
15
27
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
16
diff --git a/net/eth.c b/net/eth.c
28
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/net/e1000.c
18
--- a/net/eth.c
30
+++ b/hw/net/e1000.c
19
+++ b/net/eth.c
31
@@ -XXX,XX +XXX,XX @@ putsum(uint8_t *data, uint32_t n, uint32_t sloc, uint32_t css, uint32_t cse)
20
@@ -XXX,XX +XXX,XX @@ _eth_get_rss_ex_dst_addr(const struct iovec *pkt, int pkt_frags,
32
n = cse + 1;
21
bytes_read = iov_to_buf(pkt, pkt_frags, ext_hdr_offset,
33
if (sloc < n-1) {
22
&rt_hdr, sizeof(rt_hdr));
34
sum = net_checksum_add(n-css, data+css);
23
assert(bytes_read == sizeof(rt_hdr));
35
- stw_be_p(data + sloc, net_checksum_finish(sum));
24
-
36
+ stw_be_p(data + sloc, net_checksum_finish_nozero(sum));
25
- if ((rt_hdr.rtype == 2) && (rt_hdr.segleft == 1)) {
26
- bytes_read = iov_to_buf(pkt, pkt_frags, ext_hdr_offset + sizeof(rt_hdr),
27
- dst_addr, sizeof(*dst_addr));
28
-
29
- return bytes_read == sizeof(*dst_addr);
30
+ if ((rt_hdr.rtype != 2) || (rt_hdr.segleft != 1)) {
31
+ return false;
37
}
32
}
33
+ bytes_read = iov_to_buf(pkt, pkt_frags, ext_hdr_offset + sizeof(rt_hdr),
34
+ dst_addr, sizeof(*dst_addr));
35
+ assert(bytes_read == sizeof(*dst_addr));
36
37
- return false;
38
+ return true;
38
}
39
}
39
40
40
diff --git a/hw/net/net_rx_pkt.c b/hw/net/net_rx_pkt.c
41
static bool
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/net/net_rx_pkt.c
43
+++ b/hw/net/net_rx_pkt.c
44
@@ -XXX,XX +XXX,XX @@ _net_rx_pkt_calc_l4_csum(struct NetRxPkt *pkt)
45
cntr += net_checksum_add_iov(pkt->vec, pkt->vec_len,
46
pkt->l4hdr_off, csl, cso);
47
48
- csum = net_checksum_finish(cntr);
49
+ csum = net_checksum_finish_nozero(cntr);
50
51
trace_net_rx_pkt_l4_csum_calc_csum(pkt->l4hdr_off, csl, cntr, csum);
52
53
diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/hw/net/net_tx_pkt.c
56
+++ b/hw/net/net_tx_pkt.c
57
@@ -XXX,XX +XXX,XX @@ static void net_tx_pkt_do_sw_csum(struct NetTxPkt *pkt)
58
net_checksum_add_iov(iov, iov_len, pkt->virt_hdr.csum_start, csl, cso);
59
60
/* Put the checksum obtained into the packet */
61
- csum = cpu_to_be16(net_checksum_finish(csum_cntr));
62
+ csum = cpu_to_be16(net_checksum_finish_nozero(csum_cntr));
63
iov_from_buf(iov, iov_len, csum_offset, &csum, sizeof csum);
64
}
65
66
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/hw/net/vmxnet3.c
69
+++ b/hw/net/vmxnet3.c
70
@@ -XXX,XX +XXX,XX @@ static void vmxnet3_rx_need_csum_calculate(struct NetRxPkt *pkt,
71
data = (uint8_t *)pkt_data + vhdr->csum_start;
72
len = pkt_len - vhdr->csum_start;
73
/* Put the checksum obtained into the packet */
74
- stw_be_p(data + vhdr->csum_offset, net_raw_checksum(data, len));
75
+ stw_be_p(data + vhdr->csum_offset,
76
+ net_checksum_finish_nozero(net_checksum_add(len, data)));
77
78
vhdr->flags &= ~VIRTIO_NET_HDR_F_NEEDS_CSUM;
79
vhdr->flags |= VIRTIO_NET_HDR_F_DATA_VALID;
80
diff --git a/include/net/checksum.h b/include/net/checksum.h
81
index XXXXXXX..XXXXXXX 100644
82
--- a/include/net/checksum.h
83
+++ b/include/net/checksum.h
84
@@ -XXX,XX +XXX,XX @@ net_checksum_add(int len, uint8_t *buf)
85
}
86
87
static inline uint16_t
88
+net_checksum_finish_nozero(uint32_t sum)
89
+{
90
+ return net_checksum_finish(sum) ?: 0xFFFF;
91
+}
92
+
93
+static inline uint16_t
94
net_raw_checksum(uint8_t *data, int length)
95
{
96
return net_checksum_finish(net_checksum_add(length, data));
97
--
42
--
98
2.7.4
43
2.7.4
99
44
100
45
diff view generated by jsdifflib