aboutsummaryrefslogtreecommitdiff
path: root/hw/net/vmxnet3.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/net/vmxnet3.c')
-rw-r--r--hw/net/vmxnet3.c157
1 files changed, 76 insertions, 81 deletions
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index 41f796a247..707487c636 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -40,7 +40,6 @@
#define PCI_DEVICE_ID_VMWARE_VMXNET3_REVISION 0x1
#define VMXNET3_MSIX_BAR_SIZE 0x2000
-#define MIN_BUF_SIZE 60
/* Compatibility flags for migration */
#define VMXNET3_COMPAT_FLAG_OLD_MSI_OFFSETS_BIT 0
@@ -440,19 +439,19 @@ vmxnet3_setup_tx_offloads(VMXNET3State *s)
{
switch (s->offload_mode) {
case VMXNET3_OM_NONE:
- net_tx_pkt_build_vheader(s->tx_pkt, false, false, 0);
- break;
+ return net_tx_pkt_build_vheader(s->tx_pkt, false, false, 0);
case VMXNET3_OM_CSUM:
- net_tx_pkt_build_vheader(s->tx_pkt, false, true, 0);
VMW_PKPRN("L4 CSO requested\n");
- break;
+ return net_tx_pkt_build_vheader(s->tx_pkt, false, true, 0);
case VMXNET3_OM_TSO:
- net_tx_pkt_build_vheader(s->tx_pkt, true, true,
- s->cso_or_gso_size);
- net_tx_pkt_update_ip_checksums(s->tx_pkt);
VMW_PKPRN("GSO offload requested.");
+ if (!net_tx_pkt_build_vheader(s->tx_pkt, true, true,
+ s->cso_or_gso_size)) {
+ return false;
+ }
+ net_tx_pkt_update_ip_checksums(s->tx_pkt);
break;
default:
@@ -651,9 +650,8 @@ static void vmxnet3_process_tx_queue(VMXNET3State *s, int qidx)
data_len = (txd.len > 0) ? txd.len : VMXNET3_MAX_TX_BUF_SIZE;
data_pa = txd.addr;
- if (!net_tx_pkt_add_raw_fragment(s->tx_pkt,
- data_pa,
- data_len)) {
+ if (!net_tx_pkt_add_raw_fragment_pci(s->tx_pkt, PCI_DEVICE(s),
+ data_pa, data_len)) {
s->skip_current_tx_pkt = true;
}
}
@@ -678,9 +676,12 @@ static void vmxnet3_process_tx_queue(VMXNET3State *s, int qidx)
vmxnet3_complete_packet(s, qidx, txd_idx);
s->tx_sop = true;
s->skip_current_tx_pkt = false;
- net_tx_pkt_reset(s->tx_pkt);
+ net_tx_pkt_reset(s->tx_pkt,
+ net_tx_pkt_unmap_frag_pci, PCI_DEVICE(s));
}
}
+
+ net_tx_pkt_reset(s->tx_pkt, net_tx_pkt_unmap_frag_pci, PCI_DEVICE(s));
}
static inline void
@@ -847,21 +848,20 @@ static void vmxnet3_rx_need_csum_calculate(struct NetRxPkt *pkt,
size_t pkt_len)
{
struct virtio_net_hdr *vhdr;
- bool isip4, isip6, istcp, isudp;
+ bool hasip4, hasip6;
+ EthL4HdrProto l4hdr_proto;
uint8_t *data;
int len;
- if (!net_rx_pkt_has_virt_hdr(pkt)) {
- return;
- }
-
vhdr = net_rx_pkt_get_vhdr(pkt);
if (!VMXNET_FLAG_IS_SET(vhdr->flags, VIRTIO_NET_HDR_F_NEEDS_CSUM)) {
return;
}
- net_rx_pkt_get_protocols(pkt, &isip4, &isip6, &isudp, &istcp);
- if (!(isip4 || isip6) || !(istcp || isudp)) {
+ net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &l4hdr_proto);
+ if (!(hasip4 || hasip6) ||
+ (l4hdr_proto != ETH_L4_HDR_PROTO_TCP &&
+ l4hdr_proto != ETH_L4_HDR_PROTO_UDP)) {
return;
}
@@ -889,7 +889,8 @@ static void vmxnet3_rx_update_descr(struct NetRxPkt *pkt,
struct Vmxnet3_RxCompDesc *rxcd)
{
int csum_ok, is_gso;
- bool isip4, isip6, istcp, isudp;
+ bool hasip4, hasip6;
+ EthL4HdrProto l4hdr_proto;
struct virtio_net_hdr *vhdr;
uint8_t offload_type;
@@ -898,10 +899,6 @@ static void vmxnet3_rx_update_descr(struct NetRxPkt *pkt,
rxcd->tci = net_rx_pkt_get_vlan_tag(pkt);
}
- if (!net_rx_pkt_has_virt_hdr(pkt)) {
- goto nocsum;
- }
-
vhdr = net_rx_pkt_get_vhdr(pkt);
/*
* Checksum is valid when lower level tell so or when lower level
@@ -919,16 +916,18 @@ static void vmxnet3_rx_update_descr(struct NetRxPkt *pkt,
goto nocsum;
}
- net_rx_pkt_get_protocols(pkt, &isip4, &isip6, &isudp, &istcp);
- if ((!istcp && !isudp) || (!isip4 && !isip6)) {
+ net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &l4hdr_proto);
+ if ((l4hdr_proto != ETH_L4_HDR_PROTO_TCP &&
+ l4hdr_proto != ETH_L4_HDR_PROTO_UDP) ||
+ (!hasip4 && !hasip6)) {
goto nocsum;
}
rxcd->cnc = 0;
- rxcd->v4 = isip4 ? 1 : 0;
- rxcd->v6 = isip6 ? 1 : 0;
- rxcd->tcp = istcp ? 1 : 0;
- rxcd->udp = isudp ? 1 : 0;
+ rxcd->v4 = hasip4 ? 1 : 0;
+ rxcd->v6 = hasip6 ? 1 : 0;
+ rxcd->tcp = l4hdr_proto == ETH_L4_HDR_PROTO_TCP;
+ rxcd->udp = l4hdr_proto == ETH_L4_HDR_PROTO_UDP;
rxcd->fcs = rxcd->tuc = rxcd->ipc = 1;
return;
@@ -1161,7 +1160,6 @@ static void vmxnet3_deactivate_device(VMXNET3State *s)
{
if (s->device_active) {
VMW_CBPRN("Deactivating vmxnet3...");
- net_tx_pkt_reset(s->tx_pkt);
net_tx_pkt_uninit(s->tx_pkt);
net_rx_pkt_uninit(s->rx_pkt);
s->device_active = false;
@@ -1343,6 +1341,8 @@ static void vmxnet3_update_features(VMXNET3State *s)
s->lro_supported,
s->lro_supported,
0,
+ 0,
+ 0,
0);
}
}
@@ -1441,6 +1441,10 @@ static void vmxnet3_activate_device(VMXNET3State *s)
vmxnet3_setup_rx_filtering(s);
/* Cache fields from shared memory */
s->mtu = VMXNET3_READ_DRV_SHARED32(d, s->drv_shmem, devRead.misc.mtu);
+ if (s->mtu < VMXNET3_MIN_MTU || s->mtu > VMXNET3_MAX_MTU) {
+ qemu_log_mask(LOG_GUEST_ERROR, "vmxnet3: Bad MTU size: %u\n", s->mtu);
+ return;
+ }
VMW_CFPRN("MTU is %u", s->mtu);
s->max_rx_frags =
@@ -1486,6 +1490,9 @@ static void vmxnet3_activate_device(VMXNET3State *s)
/* Read rings memory locations for TX queues */
pa = VMXNET3_READ_TX_QUEUE_DESCR64(d, qdescr_pa, conf.txRingBasePA);
size = VMXNET3_READ_TX_QUEUE_DESCR32(d, qdescr_pa, conf.txRingSize);
+ if (size > VMXNET3_TX_RING_MAX_SIZE) {
+ size = VMXNET3_TX_RING_MAX_SIZE;
+ }
vmxnet3_ring_init(d, &s->txq_descr[i].tx_ring, pa, size,
sizeof(struct Vmxnet3_TxDesc), false);
@@ -1496,6 +1503,9 @@ static void vmxnet3_activate_device(VMXNET3State *s)
/* TXC ring */
pa = VMXNET3_READ_TX_QUEUE_DESCR64(d, qdescr_pa, conf.compRingBasePA);
size = VMXNET3_READ_TX_QUEUE_DESCR32(d, qdescr_pa, conf.compRingSize);
+ if (size > VMXNET3_TC_RING_MAX_SIZE) {
+ size = VMXNET3_TC_RING_MAX_SIZE;
+ }
vmxnet3_ring_init(d, &s->txq_descr[i].comp_ring, pa, size,
sizeof(struct Vmxnet3_TxCompDesc), true);
VMXNET3_RING_DUMP(VMW_CFPRN, "TXC", i, &s->txq_descr[i].comp_ring);
@@ -1514,9 +1524,8 @@ static void vmxnet3_activate_device(VMXNET3State *s)
/* Preallocate TX packet wrapper */
VMW_CFPRN("Max TX fragments is %u", s->max_tx_frags);
- net_tx_pkt_init(&s->tx_pkt, PCI_DEVICE(s),
- s->max_tx_frags, s->peer_has_vhdr);
- net_rx_pkt_init(&s->rx_pkt, s->peer_has_vhdr);
+ net_tx_pkt_init(&s->tx_pkt, s->max_tx_frags);
+ net_rx_pkt_init(&s->rx_pkt);
/* Read rings memory locations for RX queues */
for (i = 0; i < s->rxq_num; i++) {
@@ -1537,6 +1546,9 @@ static void vmxnet3_activate_device(VMXNET3State *s)
/* RX rings */
pa = VMXNET3_READ_RX_QUEUE_DESCR64(d, qd_pa, conf.rxRingBasePA[j]);
size = VMXNET3_READ_RX_QUEUE_DESCR32(d, qd_pa, conf.rxRingSize[j]);
+ if (size > VMXNET3_RX_RING_MAX_SIZE) {
+ size = VMXNET3_RX_RING_MAX_SIZE;
+ }
vmxnet3_ring_init(d, &s->rxq_descr[i].rx_ring[j], pa, size,
sizeof(struct Vmxnet3_RxDesc), false);
VMW_CFPRN("RX queue %d:%d: Base: %" PRIx64 ", Size: %d",
@@ -1546,6 +1558,9 @@ static void vmxnet3_activate_device(VMXNET3State *s)
/* RXC ring */
pa = VMXNET3_READ_RX_QUEUE_DESCR64(d, qd_pa, conf.compRingBasePA);
size = VMXNET3_READ_RX_QUEUE_DESCR32(d, qd_pa, conf.compRingSize);
+ if (size > VMXNET3_RC_RING_MAX_SIZE) {
+ size = VMXNET3_RC_RING_MAX_SIZE;
+ }
vmxnet3_ring_init(d, &s->rxq_descr[i].comp_ring, pa, size,
sizeof(struct Vmxnet3_RxCompDesc), true);
VMW_CFPRN("RXC queue %d: Base: %" PRIx64 ", Size: %d", i, pa, size);
@@ -1803,7 +1818,9 @@ vmxnet3_io_bar1_write(void *opaque,
case VMXNET3_REG_ICR:
VMW_CBPRN("Write BAR1 [VMXNET3_REG_ICR] = %" PRIx64 ", size %d",
val, size);
- g_assert_not_reached();
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: write to read-only register VMXNET3_REG_ICR\n",
+ TYPE_VMXNET3);
break;
/* Event Cause Register */
@@ -1872,7 +1889,7 @@ vmxnet3_io_bar1_read(void *opaque, hwaddr addr, unsigned size)
break;
default:
- VMW_CBPRN("Unknow read BAR1[%" PRIx64 "], %d bytes", addr, size);
+ VMW_CBPRN("Unknown read BAR1[%" PRIx64 "], %d bytes", addr, size);
break;
}
@@ -1964,7 +1981,6 @@ vmxnet3_receive(NetClientState *nc, const uint8_t *buf, size_t size)
{
VMXNET3State *s = qemu_get_nic_opaque(nc);
size_t bytes_indicated;
- uint8_t min_buf[MIN_BUF_SIZE];
if (!vmxnet3_can_receive(nc)) {
VMW_PKPRN("Cannot receive now");
@@ -1977,19 +1993,16 @@ vmxnet3_receive(NetClientState *nc, const uint8_t *buf, size_t size)
size -= sizeof(struct virtio_net_hdr);
}
- /* Pad to minimum Ethernet frame length */
- if (size < sizeof(min_buf)) {
- memcpy(min_buf, buf, size);
- memset(&min_buf[size], 0, sizeof(min_buf) - size);
- buf = min_buf;
- size = sizeof(min_buf);
- }
-
net_rx_pkt_set_packet_type(s->rx_pkt,
get_eth_packet_type(PKT_GET_ETH_HDR(buf)));
if (vmxnet3_rx_filter_may_indicate(s, buf, size)) {
- net_rx_pkt_set_protocols(s->rx_pkt, buf, size);
+ struct iovec iov = {
+ .iov_base = (void *)buf,
+ .iov_len = size
+ };
+
+ net_rx_pkt_set_protocols(s->rx_pkt, &iov, 1, 0);
vmxnet3_rx_need_csum_calculate(s->rx_pkt, buf, size);
net_rx_pkt_attach_data(s->rx_pkt, buf, size, s->rx_vlan_stripping);
bytes_indicated = vmxnet3_indicate_packet(s) ? size : -1;
@@ -2065,7 +2078,7 @@ static void vmxnet3_net_init(VMXNET3State *s)
s->nic = qemu_new_nic(&net_vmxnet3_info, &s->conf,
object_get_typename(OBJECT(s)),
- d->id, s);
+ d->id, &d->mem_reentrancy_guard, s);
s->peer_has_vhdr = vmxnet3_peer_has_vnet_hdr(s);
s->tx_sop = true;
@@ -2095,20 +2108,14 @@ vmxnet3_unuse_msix_vectors(VMXNET3State *s, int num_vectors)
}
}
-static bool
+static void
vmxnet3_use_msix_vectors(VMXNET3State *s, int num_vectors)
{
PCIDevice *d = PCI_DEVICE(s);
int i;
for (i = 0; i < num_vectors; i++) {
- int res = msix_vector_use(d, i);
- if (0 > res) {
- VMW_WRPRN("Failed to use MSI-X vector %d, error %d", i, res);
- vmxnet3_unuse_msix_vectors(s, i);
- return false;
- }
+ msix_vector_use(d, i);
}
- return true;
}
static bool
@@ -2126,13 +2133,8 @@ vmxnet3_init_msix(VMXNET3State *s)
VMW_WRPRN("Failed to initialize MSI-X, error %d", res);
s->msix_used = false;
} else {
- if (!vmxnet3_use_msix_vectors(s, VMXNET3_MAX_INTRS)) {
- VMW_WRPRN("Failed to use MSI-X vectors, error %d", res);
- msix_uninit(d, &s->msix_bar, &s->msix_bar);
- s->msix_used = false;
- } else {
- s->msix_used = true;
- }
+ vmxnet3_use_msix_vectors(s, VMXNET3_MAX_INTRS);
+ s->msix_used = true;
}
return s->msix_used;
}
@@ -2305,7 +2307,7 @@ static const VMStateDescription vmxstate_vmxnet3_mcast_list = {
.minimum_version_id = 1,
.pre_load = vmxnet3_mcast_list_pre_load,
.needed = vmxnet3_mc_list_needed,
- .fields = (VMStateField[]) {
+ .fields = (const VMStateField[]) {
VMSTATE_VBUFFER_UINT32(mcast_list, VMXNET3State, 0, NULL,
mcast_list_buff_size),
VMSTATE_END_OF_LIST()
@@ -2315,7 +2317,7 @@ static const VMStateDescription vmxstate_vmxnet3_mcast_list = {
static const VMStateDescription vmstate_vmxnet3_ring = {
.name = "vmxnet3-ring",
.version_id = 0,
- .fields = (VMStateField[]) {
+ .fields = (const VMStateField[]) {
VMSTATE_UINT64(pa, Vmxnet3Ring),
VMSTATE_UINT32(size, Vmxnet3Ring),
VMSTATE_UINT32(cell_size, Vmxnet3Ring),
@@ -2328,7 +2330,7 @@ static const VMStateDescription vmstate_vmxnet3_ring = {
static const VMStateDescription vmstate_vmxnet3_tx_stats = {
.name = "vmxnet3-tx-stats",
.version_id = 0,
- .fields = (VMStateField[]) {
+ .fields = (const VMStateField[]) {
VMSTATE_UINT64(TSOPktsTxOK, struct UPT1_TxStats),
VMSTATE_UINT64(TSOBytesTxOK, struct UPT1_TxStats),
VMSTATE_UINT64(ucastPktsTxOK, struct UPT1_TxStats),
@@ -2346,7 +2348,7 @@ static const VMStateDescription vmstate_vmxnet3_tx_stats = {
static const VMStateDescription vmstate_vmxnet3_txq_descr = {
.name = "vmxnet3-txq-descr",
.version_id = 0,
- .fields = (VMStateField[]) {
+ .fields = (const VMStateField[]) {
VMSTATE_STRUCT(tx_ring, Vmxnet3TxqDescr, 0, vmstate_vmxnet3_ring,
Vmxnet3Ring),
VMSTATE_STRUCT(comp_ring, Vmxnet3TxqDescr, 0, vmstate_vmxnet3_ring,
@@ -2362,7 +2364,7 @@ static const VMStateDescription vmstate_vmxnet3_txq_descr = {
static const VMStateDescription vmstate_vmxnet3_rx_stats = {
.name = "vmxnet3-rx-stats",
.version_id = 0,
- .fields = (VMStateField[]) {
+ .fields = (const VMStateField[]) {
VMSTATE_UINT64(LROPktsRxOK, struct UPT1_RxStats),
VMSTATE_UINT64(LROBytesRxOK, struct UPT1_RxStats),
VMSTATE_UINT64(ucastPktsRxOK, struct UPT1_RxStats),
@@ -2380,7 +2382,7 @@ static const VMStateDescription vmstate_vmxnet3_rx_stats = {
static const VMStateDescription vmstate_vmxnet3_rxq_descr = {
.name = "vmxnet3-rxq-descr",
.version_id = 0,
- .fields = (VMStateField[]) {
+ .fields = (const VMStateField[]) {
VMSTATE_STRUCT_ARRAY(rx_ring, Vmxnet3RxqDescr,
VMXNET3_RX_RINGS_PER_QUEUE, 0,
vmstate_vmxnet3_ring, Vmxnet3Ring),
@@ -2397,19 +2399,12 @@ static const VMStateDescription vmstate_vmxnet3_rxq_descr = {
static int vmxnet3_post_load(void *opaque, int version_id)
{
VMXNET3State *s = opaque;
- PCIDevice *d = PCI_DEVICE(s);
- net_tx_pkt_init(&s->tx_pkt, PCI_DEVICE(s),
- s->max_tx_frags, s->peer_has_vhdr);
- net_rx_pkt_init(&s->rx_pkt, s->peer_has_vhdr);
+ net_tx_pkt_init(&s->tx_pkt, s->max_tx_frags);
+ net_rx_pkt_init(&s->rx_pkt);
if (s->msix_used) {
- if (!vmxnet3_use_msix_vectors(s, VMXNET3_MAX_INTRS)) {
- VMW_WRPRN("Failed to re-use MSI-X vectors");
- msix_uninit(d, &s->msix_bar, &s->msix_bar);
- s->msix_used = false;
- return -1;
- }
+ vmxnet3_use_msix_vectors(s, VMXNET3_MAX_INTRS);
}
if (!vmxnet3_validate_queues(s)) {
@@ -2423,7 +2418,7 @@ static int vmxnet3_post_load(void *opaque, int version_id)
static const VMStateDescription vmstate_vmxnet3_int_state = {
.name = "vmxnet3-int-state",
.version_id = 0,
- .fields = (VMStateField[]) {
+ .fields = (const VMStateField[]) {
VMSTATE_BOOL(is_masked, Vmxnet3IntState),
VMSTATE_BOOL(is_pending, Vmxnet3IntState),
VMSTATE_BOOL(is_asserted, Vmxnet3IntState),
@@ -2437,7 +2432,7 @@ static const VMStateDescription vmstate_vmxnet3 = {
.minimum_version_id = 1,
.pre_save = vmxnet3_pre_save,
.post_load = vmxnet3_post_load,
- .fields = (VMStateField[]) {
+ .fields = (const VMStateField[]) {
VMSTATE_PCI_DEVICE(parent_obj, VMXNET3State),
VMSTATE_MSIX(parent_obj, VMXNET3State),
VMSTATE_BOOL(rx_packets_compound, VMXNET3State),
@@ -2473,7 +2468,7 @@ static const VMStateDescription vmstate_vmxnet3 = {
VMSTATE_END_OF_LIST()
},
- .subsections = (const VMStateDescription*[]) {
+ .subsections = (const VMStateDescription * const []) {
&vmxstate_vmxnet3_mcast_list,
NULL
}