mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-25 11:01:52 -06:00
e1000e: Always copy ethernet header
e1000e_receive_internal() used to check the iov length to determine copy the iovs to a contiguous buffer, but the check is flawed in two ways: - It does not ensure that iovcnt > 0. - It does not take virtio-net header into consideration. The size of this copy is just 18 octets, which can be even less than the code size required for checks. This (wrong) optimization is probably not worth so just remove it. Fixes:6f3fbe4ed0
("net: Introduce e1000e device emulation") Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> Signed-off-by: Jason Wang <jasowang@redhat.com> (cherry picked from commit310a128eae
) Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
This commit is contained in:
parent
5c4f2f1b60
commit
c84bcff3d3
1 changed files with 10 additions and 16 deletions
|
@ -1685,12 +1685,9 @@ static ssize_t
|
|||
e1000e_receive_internal(E1000ECore *core, const struct iovec *iov, int iovcnt,
|
||||
bool has_vnet)
|
||||
{
|
||||
static const int maximum_ethernet_hdr_len = (ETH_HLEN + 4);
|
||||
|
||||
uint32_t n = 0;
|
||||
uint8_t min_buf[ETH_ZLEN];
|
||||
uint8_t buf[ETH_ZLEN];
|
||||
struct iovec min_iov;
|
||||
uint8_t *filter_buf;
|
||||
size_t size, orig_size;
|
||||
size_t iov_ofs = 0;
|
||||
E1000E_RxRing rxr;
|
||||
|
@ -1713,24 +1710,21 @@ e1000e_receive_internal(E1000ECore *core, const struct iovec *iov, int iovcnt,
|
|||
net_rx_pkt_unset_vhdr(core->rx_pkt);
|
||||
}
|
||||
|
||||
filter_buf = iov->iov_base + iov_ofs;
|
||||
orig_size = iov_size(iov, iovcnt);
|
||||
size = orig_size - iov_ofs;
|
||||
|
||||
/* Pad to minimum Ethernet frame length */
|
||||
if (size < sizeof(min_buf)) {
|
||||
iov_to_buf(iov, iovcnt, iov_ofs, min_buf, size);
|
||||
memset(&min_buf[size], 0, sizeof(min_buf) - size);
|
||||
if (size < sizeof(buf)) {
|
||||
iov_to_buf(iov, iovcnt, iov_ofs, buf, size);
|
||||
memset(&buf[size], 0, sizeof(buf) - size);
|
||||
e1000x_inc_reg_if_not_full(core->mac, RUC);
|
||||
min_iov.iov_base = filter_buf = min_buf;
|
||||
min_iov.iov_len = size = sizeof(min_buf);
|
||||
min_iov.iov_base = buf;
|
||||
min_iov.iov_len = size = sizeof(buf);
|
||||
iovcnt = 1;
|
||||
iov = &min_iov;
|
||||
iov_ofs = 0;
|
||||
} else if (iov->iov_len < maximum_ethernet_hdr_len) {
|
||||
/* This is very unlikely, but may happen. */
|
||||
iov_to_buf(iov, iovcnt, iov_ofs, min_buf, maximum_ethernet_hdr_len);
|
||||
filter_buf = min_buf;
|
||||
} else {
|
||||
iov_to_buf(iov, iovcnt, iov_ofs, buf, ETH_HLEN + 4);
|
||||
}
|
||||
|
||||
/* Discard oversized packets if !LPE and !SBP. */
|
||||
|
@ -1739,9 +1733,9 @@ e1000e_receive_internal(E1000ECore *core, const struct iovec *iov, int iovcnt,
|
|||
}
|
||||
|
||||
net_rx_pkt_set_packet_type(core->rx_pkt,
|
||||
get_eth_packet_type(PKT_GET_ETH_HDR(filter_buf)));
|
||||
get_eth_packet_type(PKT_GET_ETH_HDR(buf)));
|
||||
|
||||
if (!e1000e_receive_filter(core, filter_buf, size)) {
|
||||
if (!e1000e_receive_filter(core, buf, size)) {
|
||||
trace_e1000e_rx_flt_dropped();
|
||||
return orig_size;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue