2
0
mirror of https://github.com/openvswitch/ovs synced 2025-09-01 14:55:18 +00:00

netdev-dpdk: fix management of pre-existing mempools.

Fix an issue on reconfiguration of pre-existing mempools.
This patch avoids to call dpdk_mp_put() - and erroneously
release the mempool - when it already exists.

CC: Mark B Kavanagh <mark.b.kavanagh@intel.com>
CC: Aaron Conole <aconole@redhat.com>
CC: Darrell Ball <dlu998@gmail.com>
Acked-by: Kevin Traynor <ktraynor@redhat.com>
Reported-by: Ciara Loftus <ciara.loftus@intel.com>
Tested-by: Ciara Loftus <ciara.loftus@intel.com>
Reported-by: Róbert Mulik <robert.mulik@ericsson.com>
Fixes: d555d9bded ("netdev-dpdk: Create separate memory pool for each port.")
Signed-off-by: Antonio Fischetti <antonio.fischetti@intel.com>
Acked-by: Mark Kavanagh <mark.b.kavanagh@intel.com>
Signed-off-by: Ian Stokes <ian.stokes@intel.com>
This commit is contained in:
antonio.fischetti@intel.com
2017-10-19 17:54:03 +01:00
committed by Ian Stokes
parent 7827edcaeb
commit b6b26021d2

View File

@@ -508,12 +508,13 @@ dpdk_mp_name(struct dpdk_mp *dmp)
} }
static struct dpdk_mp * static struct dpdk_mp *
dpdk_mp_create(struct netdev_dpdk *dev, int mtu) dpdk_mp_create(struct netdev_dpdk *dev, int mtu, bool *mp_exists)
{ {
struct dpdk_mp *dmp = dpdk_rte_mzalloc(sizeof *dmp); struct dpdk_mp *dmp = dpdk_rte_mzalloc(sizeof *dmp);
if (!dmp) { if (!dmp) {
return NULL; return NULL;
} }
*mp_exists = false;
dmp->socket_id = dev->requested_socket_id; dmp->socket_id = dev->requested_socket_id;
dmp->mtu = mtu; dmp->mtu = mtu;
ovs_strzcpy(dmp->if_name, dev->up.name, IFNAMSIZ); ovs_strzcpy(dmp->if_name, dev->up.name, IFNAMSIZ);
@@ -530,8 +531,6 @@ dpdk_mp_create(struct netdev_dpdk *dev, int mtu)
+ MIN(RTE_MAX_LCORE, dev->requested_n_rxq) * NETDEV_MAX_BURST + MIN(RTE_MAX_LCORE, dev->requested_n_rxq) * NETDEV_MAX_BURST
+ MIN_NB_MBUF; + MIN_NB_MBUF;
bool mp_exists = false;
do { do {
char *mp_name = dpdk_mp_name(dmp); char *mp_name = dpdk_mp_name(dmp);
@@ -559,7 +558,7 @@ dpdk_mp_create(struct netdev_dpdk *dev, int mtu)
/* As the mempool create returned EEXIST we can expect the /* As the mempool create returned EEXIST we can expect the
* lookup has returned a valid pointer. If for some reason * lookup has returned a valid pointer. If for some reason
* that's not the case we keep track of it. */ * that's not the case we keep track of it. */
mp_exists = true; *mp_exists = true;
} else { } else {
VLOG_ERR("Failed mempool \"%s\" create request of %u mbufs", VLOG_ERR("Failed mempool \"%s\" create request of %u mbufs",
mp_name, dmp->mp_size); mp_name, dmp->mp_size);
@@ -573,20 +572,23 @@ dpdk_mp_create(struct netdev_dpdk *dev, int mtu)
rte_mempool_obj_iter(dmp->mp, ovs_rte_pktmbuf_init, NULL); rte_mempool_obj_iter(dmp->mp, ovs_rte_pktmbuf_init, NULL);
return dmp; return dmp;
} }
} while (!mp_exists && } while (!(*mp_exists) &&
(rte_errno == ENOMEM && (dmp->mp_size /= 2) >= MIN_NB_MBUF)); (rte_errno == ENOMEM && (dmp->mp_size /= 2) >= MIN_NB_MBUF));
rte_free(dmp); rte_free(dmp);
return NULL; return NULL;
} }
/* Returns a valid pointer when either of the following is true:
* - a new mempool was just created;
* - a matching mempool already exists. */
static struct dpdk_mp * static struct dpdk_mp *
dpdk_mp_get(struct netdev_dpdk *dev, int mtu) dpdk_mp_get(struct netdev_dpdk *dev, int mtu, bool *mp_exists)
{ {
struct dpdk_mp *dmp; struct dpdk_mp *dmp;
ovs_mutex_lock(&dpdk_mp_mutex); ovs_mutex_lock(&dpdk_mp_mutex);
dmp = dpdk_mp_create(dev, mtu); dmp = dpdk_mp_create(dev, mtu, mp_exists);
ovs_mutex_unlock(&dpdk_mp_mutex); ovs_mutex_unlock(&dpdk_mp_mutex);
return dmp; return dmp;
@@ -610,9 +612,11 @@ dpdk_mp_put(struct dpdk_mp *dmp)
ovs_mutex_unlock(&dpdk_mp_mutex); ovs_mutex_unlock(&dpdk_mp_mutex);
} }
/* Tries to allocate new mempool on requested_socket_id with /* Tries to allocate a new mempool - or re-use an existing one where
* mbuf size corresponding to requested_mtu. * appropriate - on requested_socket_id with a size determined by
* On success new configuration will be applied. * requested_mtu and requested Rx/Tx queues.
* On success - or when re-using an existing mempool - the new configuration
* will be applied.
* On error, device will be left unchanged. */ * On error, device will be left unchanged. */
static int static int
netdev_dpdk_mempool_configure(struct netdev_dpdk *dev) netdev_dpdk_mempool_configure(struct netdev_dpdk *dev)
@@ -620,14 +624,22 @@ netdev_dpdk_mempool_configure(struct netdev_dpdk *dev)
{ {
uint32_t buf_size = dpdk_buf_size(dev->requested_mtu); uint32_t buf_size = dpdk_buf_size(dev->requested_mtu);
struct dpdk_mp *mp; struct dpdk_mp *mp;
bool mp_exists;
mp = dpdk_mp_get(dev, FRAME_LEN_TO_MTU(buf_size)); mp = dpdk_mp_get(dev, FRAME_LEN_TO_MTU(buf_size), &mp_exists);
if (!mp) { if (!mp) {
VLOG_ERR("Failed to create memory pool for netdev " VLOG_ERR("Failed to create memory pool for netdev "
"%s, with MTU %d on socket %d: %s\n", "%s, with MTU %d on socket %d: %s\n",
dev->up.name, dev->requested_mtu, dev->requested_socket_id, dev->up.name, dev->requested_mtu, dev->requested_socket_id,
rte_strerror(rte_errno)); rte_strerror(rte_errno));
return rte_errno; return rte_errno;
} else if (mp_exists) {
/* If a new MTU was requested and its rounded value equals the one
* that is currently used, then the existing mempool is returned.
* Update dev with the new values. */
dev->mtu = dev->requested_mtu;
dev->max_packet_len = MTU_TO_FRAME_LEN(dev->mtu);
return EEXIST;
} else { } else {
dpdk_mp_put(dev->dpdk_mp); dpdk_mp_put(dev->dpdk_mp);
dev->dpdk_mp = mp; dev->dpdk_mp = mp;
@@ -3207,7 +3219,7 @@ netdev_dpdk_reconfigure(struct netdev *netdev)
rte_eth_dev_stop(dev->port_id); rte_eth_dev_stop(dev->port_id);
err = netdev_dpdk_mempool_configure(dev); err = netdev_dpdk_mempool_configure(dev);
if (err) { if (err && err != EEXIST) {
goto out; goto out;
} }
@@ -3247,12 +3259,12 @@ dpdk_vhost_reconfigure_helper(struct netdev_dpdk *dev)
netdev_dpdk_remap_txqs(dev); netdev_dpdk_remap_txqs(dev);
err = netdev_dpdk_mempool_configure(dev); err = netdev_dpdk_mempool_configure(dev);
if (err) { if (!err) {
return err; /* A new mempool was created. */
} else {
netdev_change_seq_changed(&dev->up); netdev_change_seq_changed(&dev->up);
} else if (err != EEXIST){
return err;
} }
if (netdev_dpdk_get_vid(dev) >= 0) { if (netdev_dpdk_get_vid(dev) >= 0) {
if (dev->vhost_reconfigured == false) { if (dev->vhost_reconfigured == false) {
dev->vhost_reconfigured = true; dev->vhost_reconfigured = true;