diff options
-rw-r--r-- | lib/netdev-dpdk.c | 96 |
1 files changed, 59 insertions, 37 deletions
diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c index c60f46f87..82652f0c0 100644 --- a/lib/netdev-dpdk.c +++ b/lib/netdev-dpdk.c @@ -308,7 +308,7 @@ struct dpdk_mp { int mtu; int socket_id; char if_name[IFNAMSIZ]; - unsigned mp_size; + unsigned n_mbufs; /* Number of mbufs inside the mempool. */ struct ovs_list list_node OVS_GUARDED_BY(dpdk_mp_mutex); }; @@ -499,48 +499,55 @@ dpdk_mp_name(struct dpdk_mp *dmp) { uint32_t h = hash_string(dmp->if_name, 0); char *mp_name = xcalloc(RTE_MEMPOOL_NAMESIZE, sizeof *mp_name); - int ret = snprintf(mp_name, RTE_MEMPOOL_NAMESIZE, "ovs_%x_%d_%u", - h, dmp->mtu, dmp->mp_size); + int ret = snprintf(mp_name, RTE_MEMPOOL_NAMESIZE, "ovs_%x_%d_%d_%u", + h, dmp->socket_id, dmp->mtu, dmp->n_mbufs); if (ret < 0 || ret >= RTE_MEMPOOL_NAMESIZE) { + VLOG_DBG("snprintf returned %d. Failed to generate a mempool " + "name for \"%s\". Hash:0x%x, mtu:%d, mbufs:%u.", + ret, dmp->if_name, h, dmp->mtu, dmp->n_mbufs); return NULL; } return mp_name; } 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); if (!dmp) { return NULL; } + *mp_exists = false; dmp->socket_id = dev->requested_socket_id; dmp->mtu = mtu; ovs_strzcpy(dmp->if_name, dev->up.name, IFNAMSIZ); /* - * XXX: rough estimation of memory required for port: + * XXX: rough estimation of number of mbufs required for this port: * <packets required to fill the device rxqs> * + <packets that could be stuck on other ports txqs> * + <packets in the pmd threads> * + <additional memory for corner cases> */ - dmp->mp_size = dev->requested_n_rxq * dev->requested_rxq_size + dmp->n_mbufs = dev->requested_n_rxq * dev->requested_rxq_size + dev->requested_n_txq * dev->requested_txq_size + MIN(RTE_MAX_LCORE, dev->requested_n_rxq) * NETDEV_MAX_BURST + MIN_NB_MBUF; - bool mp_exists = false; - do { char *mp_name = dpdk_mp_name(dmp); + if (!mp_name) { + rte_free(dmp); + return NULL; + } - VLOG_DBG("Requesting a mempool of %u mbufs for netdev %s " - "with %d Rx and %d Tx queues.", - dmp->mp_size, dev->up.name, - dev->requested_n_rxq, dev->requested_n_txq); + VLOG_DBG("Port %s: Requesting a mempool of %u mbufs " + "on socket %d for %d Rx and %d Tx queues.", + dev->up.name, dmp->n_mbufs, + dev->requested_socket_id, + dev->requested_n_rxq, dev->requested_n_txq); - dmp->mp = rte_pktmbuf_pool_create(mp_name, dmp->mp_size, + dmp->mp = rte_pktmbuf_pool_create(mp_name, dmp->n_mbufs, MP_CACHE_SZ, sizeof (struct dp_packet) - sizeof (struct rte_mbuf), @@ -549,7 +556,12 @@ dpdk_mp_create(struct netdev_dpdk *dev, int mtu) dmp->socket_id); if (dmp->mp) { VLOG_DBG("Allocated \"%s\" mempool with %u mbufs", mp_name, - dmp->mp_size); + dmp->n_mbufs); + /* rte_pktmbuf_pool_create has done some initialization of the + * rte_mbuf part of each dp_packet. Some OvS specific fields + * of the packet still need to be initialized by + * ovs_rte_pktmbuf_init. */ + rte_mempool_obj_iter(dmp->mp, ovs_rte_pktmbuf_init, NULL); } else if (rte_errno == EEXIST) { /* A mempool with the same name already exists. We just * retrieve its pointer to be returned to the caller. */ @@ -559,41 +571,40 @@ dpdk_mp_create(struct netdev_dpdk *dev, int mtu) /* As the mempool create returned EEXIST we can expect the * lookup has returned a valid pointer. If for some reason * that's not the case we keep track of it. */ - mp_exists = true; + *mp_exists = true; } else { VLOG_ERR("Failed mempool \"%s\" create request of %u mbufs", - mp_name, dmp->mp_size); + mp_name, dmp->n_mbufs); } free(mp_name); if (dmp->mp) { - /* rte_pktmbuf_pool_create has done some initialization of the - * rte_mbuf part of each dp_packet, while ovs_rte_pktmbuf_init - * initializes some OVS specific fields of dp_packet. - */ - rte_mempool_obj_iter(dmp->mp, ovs_rte_pktmbuf_init, NULL); return dmp; } - } while (!mp_exists && - (rte_errno == ENOMEM && (dmp->mp_size /= 2) >= MIN_NB_MBUF)); + } while (!(*mp_exists) && + (rte_errno == ENOMEM && (dmp->n_mbufs /= 2) >= MIN_NB_MBUF)); rte_free(dmp); 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 * -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; 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); return dmp; } +/* Release an existing mempool. */ static void -dpdk_mp_put(struct dpdk_mp *dmp) +dpdk_mp_free(struct dpdk_mp *dmp) { char *mp_name; @@ -610,9 +621,11 @@ dpdk_mp_put(struct dpdk_mp *dmp) ovs_mutex_unlock(&dpdk_mp_mutex); } -/* Tries to allocate new mempool on requested_socket_id with - * mbuf size corresponding to requested_mtu. - * On success new configuration will be applied. +/* Tries to allocate a new mempool - or re-use an existing one where + * appropriate - on requested_socket_id with a size determined by + * 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. */ static int netdev_dpdk_mempool_configure(struct netdev_dpdk *dev) @@ -620,16 +633,25 @@ netdev_dpdk_mempool_configure(struct netdev_dpdk *dev) { uint32_t buf_size = dpdk_buf_size(dev->requested_mtu); 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) { VLOG_ERR("Failed to create memory pool for netdev " "%s, with MTU %d on socket %d: %s\n", dev->up.name, dev->requested_mtu, dev->requested_socket_id, rte_strerror(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 { - dpdk_mp_put(dev->dpdk_mp); + /* A new mempool was created, release the previous one. */ + dpdk_mp_free(dev->dpdk_mp); dev->dpdk_mp = mp; dev->mtu = dev->requested_mtu; dev->socket_id = dev->requested_socket_id; @@ -1074,7 +1096,7 @@ common_destruct(struct netdev_dpdk *dev) OVS_EXCLUDED(dev->mutex) { rte_free(dev->tx_q); - dpdk_mp_put(dev->dpdk_mp); + dpdk_mp_free(dev->dpdk_mp); ovs_list_remove(&dev->list_node); free(ovsrcu_get_protected(struct ingress_policer *, @@ -3207,7 +3229,7 @@ netdev_dpdk_reconfigure(struct netdev *netdev) rte_eth_dev_stop(dev->port_id); err = netdev_dpdk_mempool_configure(dev); - if (err) { + if (err && err != EEXIST) { goto out; } @@ -3247,12 +3269,12 @@ dpdk_vhost_reconfigure_helper(struct netdev_dpdk *dev) netdev_dpdk_remap_txqs(dev); err = netdev_dpdk_mempool_configure(dev); - if (err) { - return err; - } else { + if (!err) { + /* A new mempool was created. */ netdev_change_seq_changed(&dev->up); + } else if (err != EEXIST){ + return err; } - if (netdev_dpdk_get_vid(dev) >= 0) { if (dev->vhost_reconfigured == false) { dev->vhost_reconfigured = true; |