mirror of
https://github.com/openvswitch/ovs
synced 2025-08-31 06:15:47 +00:00
netdev-dpdk: Fix calling vhost API with negative vid.
Currently, rx and tx functions for vhost interfaces always obtain
'vid' twice. First time inside 'is_vhost_running' for checking
the value and the second time in enqueue/dequeue function calls to
send/receive packets. But second time we're not checking the
returned value. If vhost device will be destroyed between
checking and enqueue/dequeue, DPDK API will be called with
'-1' instead of valid 'vid'. DPDK API does not validate the 'vid'.
This leads to getting random memory value as a pointer to internal
device structure inside DPDK. Access by this pointer leads to
segmentation fault. For example:
|00503|dpdk|INFO|VHOST_CONFIG: read message VHOST_USER_GET_VRING_BASE
[New Thread 0x7fb6754910 (LWP 21246)]
Program received signal SIGSEGV, Segmentation fault.
rte_vhost_enqueue_burst at lib/librte_vhost/virtio_net.c:630
630 if (dev->features & (1 << VIRTIO_NET_F_MRG_RXBUF))
(gdb) bt full
#0 rte_vhost_enqueue_burst at lib/librte_vhost/virtio_net.c:630
dev = 0xffffffff
#1 __netdev_dpdk_vhost_send at lib/netdev-dpdk.c:1803
tx_pkts = <optimized out>
cur_pkts = 0x7f340084f0
total_pkts = 32
dropped = 0
i = <optimized out>
retries = 0
...
(gdb) p *((struct netdev_dpdk *) netdev)
$8 = { ... ,
flags = (NETDEV_UP | NETDEV_PROMISC), ... ,
vid = {v = -1},
vhost_reconfigured = false, ... }
Issue can be reproduced by stopping DPDK application (testpmd) inside
guest while heavy traffic flows to this VM.
Fix that by obtaining and checking the 'vid' only once.
CC: Ciara Loftus <ciara.loftus@intel.com>
Fixes: 0a0f39df1d
("netdev-dpdk: Add support for DPDK 16.07")
Signed-off-by: Ilya Maximets <i.maximets@samsung.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
Tested-by: Billy O'Mahony <billy.o.mahony@intel.com>
Acked-by: Billy O'Mahony <billy.o.mahony@intel.com>
Signed-off-by: Ian Stokes <ian.stokes@intel.com>
This commit is contained in:
committed by
Ian Stokes
parent
bc57ed901f
commit
daf22bf7a8
@@ -1606,18 +1606,18 @@ netdev_dpdk_vhost_rxq_recv(struct netdev_rxq *rxq,
|
||||
struct dp_packet_batch *batch)
|
||||
{
|
||||
struct netdev_dpdk *dev = netdev_dpdk_cast(rxq->netdev);
|
||||
int qid = rxq->queue_id;
|
||||
struct ingress_policer *policer = netdev_dpdk_get_ingress_policer(dev);
|
||||
uint16_t nb_rx = 0;
|
||||
uint16_t dropped = 0;
|
||||
int qid = rxq->queue_id;
|
||||
int vid = netdev_dpdk_get_vid(dev);
|
||||
|
||||
if (OVS_UNLIKELY(!is_vhost_running(dev)
|
||||
if (OVS_UNLIKELY(vid < 0 || !dev->vhost_reconfigured
|
||||
|| !(dev->flags & NETDEV_UP))) {
|
||||
return EAGAIN;
|
||||
}
|
||||
|
||||
nb_rx = rte_vhost_dequeue_burst(netdev_dpdk_get_vid(dev),
|
||||
qid * VIRTIO_QNUM + VIRTIO_TXQ,
|
||||
nb_rx = rte_vhost_dequeue_burst(vid, qid * VIRTIO_QNUM + VIRTIO_TXQ,
|
||||
dev->mp,
|
||||
(struct rte_mbuf **) batch->packets,
|
||||
NETDEV_MAX_BURST);
|
||||
@@ -1752,10 +1752,11 @@ __netdev_dpdk_vhost_send(struct netdev *netdev, int qid,
|
||||
unsigned int total_pkts = cnt;
|
||||
unsigned int dropped = 0;
|
||||
int i, retries = 0;
|
||||
int vid = netdev_dpdk_get_vid(dev);
|
||||
|
||||
qid = dev->tx_q[qid % netdev->n_txq].map;
|
||||
|
||||
if (OVS_UNLIKELY(!is_vhost_running(dev) || qid < 0
|
||||
if (OVS_UNLIKELY(vid < 0 || !dev->vhost_reconfigured || qid < 0
|
||||
|| !(dev->flags & NETDEV_UP))) {
|
||||
rte_spinlock_lock(&dev->stats_lock);
|
||||
dev->stats.tx_dropped+= cnt;
|
||||
@@ -1774,8 +1775,7 @@ __netdev_dpdk_vhost_send(struct netdev *netdev, int qid,
|
||||
int vhost_qid = qid * VIRTIO_QNUM + VIRTIO_RXQ;
|
||||
unsigned int tx_pkts;
|
||||
|
||||
tx_pkts = rte_vhost_enqueue_burst(netdev_dpdk_get_vid(dev),
|
||||
vhost_qid, cur_pkts, cnt);
|
||||
tx_pkts = rte_vhost_enqueue_burst(vid, vhost_qid, cur_pkts, cnt);
|
||||
if (OVS_LIKELY(tx_pkts)) {
|
||||
/* Packets have been sent.*/
|
||||
cnt -= tx_pkts;
|
||||
|
Reference in New Issue
Block a user