mirror of https://github.com/xemu-project/xemu.git
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1 iQEcBAABAgAGBQJVrS76AAoJEJykq7OBq3PIMmMH/0mW/ClwudW80iOcTKrdHSPJ Fha4gy3m1GNt1sa0uvKxCivgF9H1RDmiCJRajaYsvlZYlQ/y15r6gqs3R+BAe2RX PVuJw0mB1pglsqJ2EBSiFQXGqLUnu2nWw9uH+URVtK9Ek7pVgNMZGRm/dhOFIxVC VGSchZrWvcARH1YoYRONebRVjXn5M4hNLtwEmcIiAZIvmHFPc88UAIkatCblCdAP BPQcR7FPUyuDZrGvT4UGjEUo62u7Hz+81MVfoAZsOQAY0QPzoZPpKIo17UFxxbsS qe2fwvtUjLhYwSozhP6JGAtlp6RG+9wOKHNBFswzU8VywT3Lt0ACcgz1xDKCE1s= =agJl -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/stefanha/tags/net-pull-request' into staging # gpg: Signature made Mon Jul 20 18:25:14 2015 BST using RSA key ID 81AB73C8 # gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>" # gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>" * remotes/stefanha/tags/net-pull-request: net: Flush queued packets when guest resumes lan9118: Drop lan9118_can_receive etraxfs_eth: Drop eth_can_receive musicpal: Drop eth_can_receive net/vmxnet3: Fix RX TCP/UDP checksum on partially summed packets net/vmxnet3: Refactor 'vmxnet_rx_pkt_attach_data' socket: pass correct size in net_socket_send() Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
bd03a38fdf
|
@ -187,11 +187,6 @@ static void eth_rx_desc_get(uint32_t addr, mv88w8618_rx_desc *desc)
|
|||
le32_to_cpus(&desc->next);
|
||||
}
|
||||
|
||||
static int eth_can_receive(NetClientState *nc)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static ssize_t eth_receive(NetClientState *nc, const uint8_t *buf, size_t size)
|
||||
{
|
||||
mv88w8618_eth_state *s = qemu_get_nic_opaque(nc);
|
||||
|
@ -381,7 +376,6 @@ static void eth_cleanup(NetClientState *nc)
|
|||
static NetClientInfo net_mv88w8618_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.can_receive = eth_can_receive,
|
||||
.receive = eth_receive,
|
||||
.cleanup = eth_cleanup,
|
||||
};
|
||||
|
|
|
@ -520,11 +520,6 @@ static int eth_match_groupaddr(ETRAXFSEthState *eth, const unsigned char *sa)
|
|||
return match;
|
||||
}
|
||||
|
||||
static int eth_can_receive(NetClientState *nc)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static ssize_t eth_receive(NetClientState *nc, const uint8_t *buf, size_t size)
|
||||
{
|
||||
unsigned char sa_bcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
|
@ -584,7 +579,6 @@ static const MemoryRegionOps eth_ops = {
|
|||
static NetClientInfo net_etraxfs_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.can_receive = eth_can_receive,
|
||||
.receive = eth_receive,
|
||||
.link_status_changed = eth_set_link,
|
||||
};
|
||||
|
|
|
@ -461,11 +461,6 @@ static void lan9118_reset(DeviceState *d)
|
|||
lan9118_reload_eeprom(s);
|
||||
}
|
||||
|
||||
static int lan9118_can_receive(NetClientState *nc)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void rx_fifo_push(lan9118_state *s, uint32_t val)
|
||||
{
|
||||
int fifo_pos;
|
||||
|
@ -1312,7 +1307,6 @@ static const MemoryRegionOps lan9118_16bit_mem_ops = {
|
|||
static NetClientInfo net_lan9118_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.can_receive = lan9118_can_receive,
|
||||
.receive = lan9118_receive,
|
||||
.link_status_changed = lan9118_set_link,
|
||||
};
|
||||
|
|
|
@ -885,6 +885,63 @@ vmxnet3_get_next_rx_descr(VMXNET3State *s, bool is_head,
|
|||
}
|
||||
}
|
||||
|
||||
/* In case packet was csum offloaded (either NEEDS_CSUM or DATA_VALID),
|
||||
* the implementation always passes an RxCompDesc with a "Checksum
|
||||
* calculated and found correct" to the OS (cnc=0 and tuc=1, see
|
||||
* vmxnet3_rx_update_descr). This emulates the observed ESXi behavior.
|
||||
*
|
||||
* Therefore, if packet has the NEEDS_CSUM set, we must calculate
|
||||
* and place a fully computed checksum into the tcp/udp header.
|
||||
* Otherwise, the OS driver will receive a checksum-correct indication
|
||||
* (CHECKSUM_UNNECESSARY), but with the actual tcp/udp checksum field
|
||||
* having just the pseudo header csum value.
|
||||
*
|
||||
* While this is not a problem if packet is destined for local delivery,
|
||||
* in the case the host OS performs forwarding, it will forward an
|
||||
* incorrectly checksummed packet.
|
||||
*/
|
||||
static void vmxnet3_rx_need_csum_calculate(struct VmxnetRxPkt *pkt,
|
||||
const void *pkt_data,
|
||||
size_t pkt_len)
|
||||
{
|
||||
struct virtio_net_hdr *vhdr;
|
||||
bool isip4, isip6, istcp, isudp;
|
||||
uint8_t *data;
|
||||
int len;
|
||||
|
||||
if (!vmxnet_rx_pkt_has_virt_hdr(pkt)) {
|
||||
return;
|
||||
}
|
||||
|
||||
vhdr = vmxnet_rx_pkt_get_vhdr(pkt);
|
||||
if (!VMXNET_FLAG_IS_SET(vhdr->flags, VIRTIO_NET_HDR_F_NEEDS_CSUM)) {
|
||||
return;
|
||||
}
|
||||
|
||||
vmxnet_rx_pkt_get_protocols(pkt, &isip4, &isip6, &isudp, &istcp);
|
||||
if (!(isip4 || isip6) || !(istcp || isudp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
vmxnet3_dump_virt_hdr(vhdr);
|
||||
|
||||
/* Validate packet len: csum_start + scum_offset + length of csum field */
|
||||
if (pkt_len < (vhdr->csum_start + vhdr->csum_offset + 2)) {
|
||||
VMW_PKPRN("packet len:%d < csum_start(%d) + csum_offset(%d) + 2, "
|
||||
"cannot calculate checksum",
|
||||
len, vhdr->csum_start, vhdr->csum_offset);
|
||||
return;
|
||||
}
|
||||
|
||||
data = (uint8_t *)pkt_data + vhdr->csum_start;
|
||||
len = pkt_len - vhdr->csum_start;
|
||||
/* Put the checksum obtained into the packet */
|
||||
stw_be_p(data + vhdr->csum_offset, net_raw_checksum(data, len));
|
||||
|
||||
vhdr->flags &= ~VIRTIO_NET_HDR_F_NEEDS_CSUM;
|
||||
vhdr->flags |= VIRTIO_NET_HDR_F_DATA_VALID;
|
||||
}
|
||||
|
||||
static void vmxnet3_rx_update_descr(struct VmxnetRxPkt *pkt,
|
||||
struct Vmxnet3_RxCompDesc *rxcd)
|
||||
{
|
||||
|
@ -1897,6 +1954,8 @@ vmxnet3_receive(NetClientState *nc, const uint8_t *buf, size_t size)
|
|||
get_eth_packet_type(PKT_GET_ETH_HDR(buf)));
|
||||
|
||||
if (vmxnet3_rx_filter_may_indicate(s, buf, size)) {
|
||||
vmxnet_rx_pkt_set_protocols(s->rx_pkt, buf, size);
|
||||
vmxnet3_rx_need_csum_calculate(s->rx_pkt, buf, size);
|
||||
vmxnet_rx_pkt_attach_data(s->rx_pkt, buf, size, s->rx_vlan_stripping);
|
||||
bytes_indicated = vmxnet3_indicate_packet(s) ? size : -1;
|
||||
if (bytes_indicated < size) {
|
||||
|
|
|
@ -92,9 +92,6 @@ void vmxnet_rx_pkt_attach_data(struct VmxnetRxPkt *pkt, const void *data,
|
|||
}
|
||||
|
||||
pkt->tci = tci;
|
||||
|
||||
eth_get_protocols(data, len, &pkt->isip4, &pkt->isip6,
|
||||
&pkt->isudp, &pkt->istcp);
|
||||
}
|
||||
|
||||
void vmxnet_rx_pkt_dump(struct VmxnetRxPkt *pkt)
|
||||
|
@ -131,6 +128,15 @@ size_t vmxnet_rx_pkt_get_total_len(struct VmxnetRxPkt *pkt)
|
|||
return pkt->tot_len;
|
||||
}
|
||||
|
||||
void vmxnet_rx_pkt_set_protocols(struct VmxnetRxPkt *pkt, const void *data,
|
||||
size_t len)
|
||||
{
|
||||
assert(pkt);
|
||||
|
||||
eth_get_protocols(data, len, &pkt->isip4, &pkt->isip6,
|
||||
&pkt->isudp, &pkt->istcp);
|
||||
}
|
||||
|
||||
void vmxnet_rx_pkt_get_protocols(struct VmxnetRxPkt *pkt,
|
||||
bool *isip4, bool *isip6,
|
||||
bool *isudp, bool *istcp)
|
||||
|
|
|
@ -54,6 +54,17 @@ void vmxnet_rx_pkt_init(struct VmxnetRxPkt **pkt, bool has_virt_hdr);
|
|||
*/
|
||||
size_t vmxnet_rx_pkt_get_total_len(struct VmxnetRxPkt *pkt);
|
||||
|
||||
/**
|
||||
* parse and set packet analysis results
|
||||
*
|
||||
* @pkt: packet
|
||||
* @data: pointer to the data buffer to be parsed
|
||||
* @len: data length
|
||||
*
|
||||
*/
|
||||
void vmxnet_rx_pkt_set_protocols(struct VmxnetRxPkt *pkt, const void *data,
|
||||
size_t len);
|
||||
|
||||
/**
|
||||
* fetches packet analysis results
|
||||
*
|
||||
|
|
19
net/net.c
19
net/net.c
|
@ -1257,14 +1257,19 @@ void qmp_set_link(const char *name, bool up, Error **errp)
|
|||
static void net_vm_change_state_handler(void *opaque, int running,
|
||||
RunState state)
|
||||
{
|
||||
/* Complete all queued packets, to guarantee we don't modify
|
||||
* state later when VM is not running.
|
||||
*/
|
||||
if (!running) {
|
||||
NetClientState *nc;
|
||||
NetClientState *tmp;
|
||||
NetClientState *nc;
|
||||
NetClientState *tmp;
|
||||
|
||||
QTAILQ_FOREACH_SAFE(nc, &net_clients, next, tmp) {
|
||||
QTAILQ_FOREACH_SAFE(nc, &net_clients, next, tmp) {
|
||||
if (running) {
|
||||
/* Flush queued packets and wake up backends. */
|
||||
if (nc->peer && qemu_can_send_packet(nc)) {
|
||||
qemu_flush_queued_packets(nc->peer);
|
||||
}
|
||||
} else {
|
||||
/* Complete all queued packets, to guarantee we don't modify
|
||||
* state later when VM is not running.
|
||||
*/
|
||||
qemu_flush_or_purge_queued_packets(nc, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -213,7 +213,7 @@ static void net_socket_send(void *opaque)
|
|||
if (s->index >= s->packet_len) {
|
||||
s->index = 0;
|
||||
s->state = 0;
|
||||
if (qemu_send_packet_async(&s->nc, s->buf, size,
|
||||
if (qemu_send_packet_async(&s->nc, s->buf, s->packet_len,
|
||||
net_socket_send_completed) == 0) {
|
||||
net_socket_read_poll(s, false);
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue