-----BEGIN PGP SIGNATURE-----
iQEzBAABCAAdFiEEIV1G9IJGaJ7HfzVi7wSWWzmNYhEFAmkWo9EACgkQ7wSWWzmN YhHargf/Uf801PmKskryVENF9sVe6u5NxJZlT3BUJVsSTGitucBIHWZ5J7MMR1lw If4tfMho3BX5Wrtl5GuCEzolk9pCz3wmSN6nyOU25C5tKaoJ/uR135K25D0CwVmD eTOyg+gKktVfogXxJ/zwZpRHMq4XXrk/C2ZP41r/CdcLyaeuDS9GIbd/q4N7f3vv bEsVqECzjEwWr2JBY9SD0xlIRp3nWwEvRsgRZPzBiQzfjSTlImqGLUsxIpF5V2LV 1BU0V/FShWyrwckBXSqCWBUh6uBUGgEl6qKnK4vH7+ed4Kd9giyp1vWAFEjHgIg+ gZtPaT/MJQOtLyCuzfuSdUpAzz5Sfw== =Is8a -----END PGP SIGNATURE----- Merge tag 'net-pull-request' of https://github.com/jasowang/qemu into staging # -----BEGIN PGP SIGNATURE----- # # iQEzBAABCAAdFiEEIV1G9IJGaJ7HfzVi7wSWWzmNYhEFAmkWo9EACgkQ7wSWWzmN # YhHargf/Uf801PmKskryVENF9sVe6u5NxJZlT3BUJVsSTGitucBIHWZ5J7MMR1lw # If4tfMho3BX5Wrtl5GuCEzolk9pCz3wmSN6nyOU25C5tKaoJ/uR135K25D0CwVmD # eTOyg+gKktVfogXxJ/zwZpRHMq4XXrk/C2ZP41r/CdcLyaeuDS9GIbd/q4N7f3vv # bEsVqECzjEwWr2JBY9SD0xlIRp3nWwEvRsgRZPzBiQzfjSTlImqGLUsxIpF5V2LV # 1BU0V/FShWyrwckBXSqCWBUh6uBUGgEl6qKnK4vH7+ed4Kd9giyp1vWAFEjHgIg+ # gZtPaT/MJQOtLyCuzfuSdUpAzz5Sfw== # =Is8a # -----END PGP SIGNATURE----- # gpg: Signature made Fri 14 Nov 2025 04:36:49 AM CET # gpg: using RSA key 215D46F48246689EC77F3562EF04965B398D6211 # gpg: Good signature from "Jason Wang (Jason Wang on RedHat) <jasowang@redhat.com>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 215D 46F4 8246 689E C77F 3562 EF04 965B 398D 6211 * tag 'net-pull-request' of https://github.com/jasowang/qemu: net: pad packets to minimum length in qemu_receive_packet() hw/net/e1000e_core: Adjust e1000e_write_payload_frag_to_rx_buffers() assert hw/net/e1000e_core: Correct rx oversize packet checks hw/net/e1000e_core: Don't advance desc_offset for NULL buffer RX descriptors net/hub: make net_hub_port_cleanup idempotent Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
409be85c2f
3 changed files with 76 additions and 27 deletions
|
|
@ -1392,10 +1392,13 @@ e1000e_write_payload_frag_to_rx_buffers(E1000ECore *core,
|
|||
dma_addr_t data_len)
|
||||
{
|
||||
while (data_len > 0) {
|
||||
uint32_t cur_buf_len = core->rxbuf_sizes[bastate->cur_idx];
|
||||
uint32_t cur_buf_bytes_left = cur_buf_len -
|
||||
bastate->written[bastate->cur_idx];
|
||||
uint32_t bytes_to_write = MIN(data_len, cur_buf_bytes_left);
|
||||
uint32_t cur_buf_len, cur_buf_bytes_left, bytes_to_write;
|
||||
|
||||
assert(bastate->cur_idx < MAX_PS_BUFFERS);
|
||||
|
||||
cur_buf_len = core->rxbuf_sizes[bastate->cur_idx];
|
||||
cur_buf_bytes_left = cur_buf_len - bastate->written[bastate->cur_idx];
|
||||
bytes_to_write = MIN(data_len, cur_buf_bytes_left);
|
||||
|
||||
trace_e1000e_rx_desc_buff_write(bastate->cur_idx,
|
||||
ba[bastate->cur_idx],
|
||||
|
|
@ -1414,8 +1417,6 @@ e1000e_write_payload_frag_to_rx_buffers(E1000ECore *core,
|
|||
if (bastate->written[bastate->cur_idx] == cur_buf_len) {
|
||||
bastate->cur_idx++;
|
||||
}
|
||||
|
||||
assert(bastate->cur_idx < MAX_PS_BUFFERS);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1481,7 +1482,6 @@ e1000e_write_packet_to_guest(E1000ECore *core, struct NetRxPkt *pkt,
|
|||
PCIDevice *d = core->owner;
|
||||
dma_addr_t base;
|
||||
union e1000_rx_desc_union desc;
|
||||
size_t desc_size;
|
||||
size_t desc_offset = 0;
|
||||
size_t iov_ofs = 0;
|
||||
|
||||
|
|
@ -1496,16 +1496,17 @@ e1000e_write_packet_to_guest(E1000ECore *core, struct NetRxPkt *pkt,
|
|||
rxi = rxr->i;
|
||||
|
||||
do {
|
||||
/*
|
||||
* Loop processing descriptors while we have packet data to
|
||||
* DMA to the guest. desc_offset tracks how much data we have
|
||||
* sent to the guest in total over all descriptors, and goes
|
||||
* from 0 up to total_size (the size of everything to send to
|
||||
* the guest including possible trailing 4 bytes of CRC data).
|
||||
*/
|
||||
hwaddr ba[MAX_PS_BUFFERS];
|
||||
E1000EBAState bastate = { { 0 } };
|
||||
bool is_last = false;
|
||||
|
||||
desc_size = total_size - desc_offset;
|
||||
|
||||
if (desc_size > core->rx_desc_buf_size) {
|
||||
desc_size = core->rx_desc_buf_size;
|
||||
}
|
||||
|
||||
if (e1000e_ring_empty(core, rxi)) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -1519,17 +1520,27 @@ e1000e_write_packet_to_guest(E1000ECore *core, struct NetRxPkt *pkt,
|
|||
e1000e_read_rx_descr(core, &desc, ba);
|
||||
|
||||
if (ba[0]) {
|
||||
/* Total amount of data DMA'd to the guest in this iteration */
|
||||
size_t desc_size = 0;
|
||||
/*
|
||||
* Total space available in this descriptor (we will update
|
||||
* this as we use it up)
|
||||
*/
|
||||
size_t rx_desc_buf_size = core->rx_desc_buf_size;
|
||||
|
||||
if (desc_offset < size) {
|
||||
static const uint32_t fcs_pad;
|
||||
size_t iov_copy;
|
||||
/* Amount of data to copy from the incoming packet */
|
||||
size_t copy_size = size - desc_offset;
|
||||
if (copy_size > core->rx_desc_buf_size) {
|
||||
copy_size = core->rx_desc_buf_size;
|
||||
}
|
||||
|
||||
/* For PS mode copy the packet header first */
|
||||
if (do_ps) {
|
||||
if (is_first) {
|
||||
/*
|
||||
* e1000e_do_ps() guarantees that buffer 0 has enough
|
||||
* space for the header; otherwise we will not split
|
||||
* the packet (i.e. do_ps is false).
|
||||
*/
|
||||
size_t ps_hdr_copied = 0;
|
||||
do {
|
||||
iov_copy = MIN(ps_hdr_len - ps_hdr_copied,
|
||||
|
|
@ -1551,14 +1562,26 @@ e1000e_write_packet_to_guest(E1000ECore *core, struct NetRxPkt *pkt,
|
|||
} while (ps_hdr_copied < ps_hdr_len);
|
||||
|
||||
is_first = false;
|
||||
desc_size += ps_hdr_len;
|
||||
} else {
|
||||
/* Leave buffer 0 of each descriptor except first */
|
||||
/* empty as per spec 7.1.5.1 */
|
||||
e1000e_write_hdr_frag_to_rx_buffers(core, ba, &bastate,
|
||||
NULL, 0);
|
||||
}
|
||||
rx_desc_buf_size -= core->rxbuf_sizes[0];
|
||||
}
|
||||
|
||||
/*
|
||||
* Clamp the amount of packet data we copy into what will fit
|
||||
* into the remaining buffers in the descriptor.
|
||||
*/
|
||||
if (copy_size > rx_desc_buf_size) {
|
||||
copy_size = rx_desc_buf_size;
|
||||
}
|
||||
desc_size += copy_size;
|
||||
rx_desc_buf_size -= copy_size;
|
||||
|
||||
/* Copy packet payload */
|
||||
while (copy_size) {
|
||||
iov_copy = MIN(copy_size, iov->iov_len - iov_ofs);
|
||||
|
|
@ -1575,20 +1598,30 @@ e1000e_write_packet_to_guest(E1000ECore *core, struct NetRxPkt *pkt,
|
|||
iov_ofs = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (desc_offset + desc_size >= total_size) {
|
||||
/* Simulate FCS checksum presence in the last descriptor */
|
||||
e1000e_write_payload_frag_to_rx_buffers(core, ba, &bastate,
|
||||
(const char *) &fcs_pad, e1000x_fcs_len(core->mac));
|
||||
}
|
||||
if (rx_desc_buf_size &&
|
||||
desc_offset >= size && desc_offset < total_size) {
|
||||
/*
|
||||
* We are in the last 4 bytes corresponding to the FCS checksum.
|
||||
* We only ever write zeroes here (unlike the hardware).
|
||||
*/
|
||||
static const uint32_t fcs_pad;
|
||||
/* Amount of space for the trailing checksum */
|
||||
size_t fcs_len = MIN(rx_desc_buf_size,
|
||||
total_size - desc_offset);
|
||||
e1000e_write_payload_frag_to_rx_buffers(core, ba, &bastate,
|
||||
(const char *)&fcs_pad,
|
||||
fcs_len);
|
||||
desc_size += fcs_len;
|
||||
}
|
||||
desc_offset += desc_size;
|
||||
if (desc_offset >= total_size) {
|
||||
is_last = true;
|
||||
}
|
||||
} else { /* as per intel docs; skip descriptors with null buf addr */
|
||||
trace_e1000e_rx_null_descriptor();
|
||||
}
|
||||
desc_offset += desc_size;
|
||||
if (desc_offset >= total_size) {
|
||||
is_last = true;
|
||||
}
|
||||
|
||||
e1000e_write_rx_descr(core, &desc, is_last ? core->rx_pkt : NULL,
|
||||
rss_info, do_ps ? ps_hdr_len : 0, &bastate.written);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ typedef struct NetHubPort {
|
|||
QLIST_ENTRY(NetHubPort) next;
|
||||
NetHub *hub;
|
||||
int id;
|
||||
bool listed;
|
||||
} NetHubPort;
|
||||
|
||||
struct NetHub {
|
||||
|
|
@ -129,7 +130,10 @@ static void net_hub_port_cleanup(NetClientState *nc)
|
|||
{
|
||||
NetHubPort *port = DO_UPCAST(NetHubPort, nc, nc);
|
||||
|
||||
QLIST_REMOVE(port, next);
|
||||
if (port->listed) {
|
||||
QLIST_REMOVE(port, next);
|
||||
port->listed = false;
|
||||
}
|
||||
}
|
||||
|
||||
static NetClientInfo net_hub_port_info = {
|
||||
|
|
@ -159,8 +163,10 @@ static NetHubPort *net_hub_port_new(NetHub *hub, const char *name,
|
|||
port = DO_UPCAST(NetHubPort, nc, nc);
|
||||
port->id = id;
|
||||
port->hub = hub;
|
||||
port->listed = false;
|
||||
|
||||
QLIST_INSERT_HEAD(&hub->ports, port, next);
|
||||
port->listed = true;
|
||||
|
||||
return port;
|
||||
}
|
||||
|
|
|
|||
10
net/net.c
10
net/net.c
|
|
@ -775,10 +775,20 @@ ssize_t qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size)
|
|||
|
||||
ssize_t qemu_receive_packet(NetClientState *nc, const uint8_t *buf, int size)
|
||||
{
|
||||
uint8_t min_pkt[ETH_ZLEN];
|
||||
size_t min_pktsz = sizeof(min_pkt);
|
||||
|
||||
if (!qemu_can_receive_packet(nc)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (net_peer_needs_padding(nc)) {
|
||||
if (eth_pad_short_frame(min_pkt, &min_pktsz, buf, size)) {
|
||||
buf = min_pkt;
|
||||
size = min_pktsz;
|
||||
}
|
||||
}
|
||||
|
||||
return qemu_net_queue_receive(nc->incoming_queue, buf, size);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue