[v14,2/2] kni: support IOVA mode
Checks
Commit Message
From: David Marchand <david.marchand@redhat.com>
Current KNI implementation only operates in IOVA_PA mode
patch adds required functionality to enable KNI in
IOVA_VA mode.
Due to IOVA to KVA address translations, based on the KNI
use case there can be a performance impact.
To mitigate the impact on performance,forcing IOVA to PA
via eal "--iova-mode=pa" option can be used, IOVA_DC bus
iommu scheme can also result in IOVA as PA.
During KNI creation, app's iova_mode details are passed to
the KNI kernel module, accordingly kernel module translates
PA/IOVA addresses to KVA and vice-versa.
Signed-off-by: David Marchand <david.marchand@redhat.com>
Signed-off-by: Vamsi Attunuru <vattunuru@marvell.com>
Signed-off-by: Kiran Kumar K <kirankumark@marvell.com>
---
doc/guides/prog_guide/kernel_nic_interface.rst | 14 ++++++++++++++
doc/guides/rel_notes/release_19_11.rst | 13 ++++++++++++-
lib/librte_eal/linux/eal/eal.c | 11 +++++++++--
lib/librte_kni/rte_kni.c | 5 +++++
4 files changed, 40 insertions(+), 3 deletions(-)
@@ -300,6 +300,20 @@ The sk_buff is then freed and the mbuf sent in the tx_q FIFO.
The DPDK TX thread dequeues the mbuf and sends it to the PMD via ``rte_eth_tx_burst()``.
It then puts the mbuf back in the cache.
+IOVA = VA: Support
+------------------
+
+KNI operates in IOVA_VA scheme when
+
+- LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0) and
+- eal option `iova-mode=va` is passed or bus IOVA scheme in the DPDK is selected
+ as RTE_IOVA_VA.
+
+Due to IOVA to KVA address translations, based on the KNI use case there
+can be a performance impact. For mitigation, forcing IOVA to PA via eal
+"--iova-mode=pa" option can be used, IOVA_DC bus iommu scheme can also
+result in IOVA as PA.
+
Ethtool
-------
@@ -292,8 +292,19 @@ New Features
compilers store their internal representation of the source code that
the linker uses at the final stage of compilation process.
- See :doc:`../prog_guide/lto` for more information:
+* **Added IOVA as VA support for KNI.**
+
+ * Added IOVA = VA support for KNI, KNI can operate in IOVA = VA mode when
+ `iova-mode=va` eal option is passed to the application or when bus IOVA
+ scheme is selected as RTE_IOVA_VA. This mode only works on Linux Kernel
+ versions 4.6.0 and above.
+ * Due to IOVA to KVA address translations, based on the KNI use case there
+ can be a performance impact. For mitigation, forcing IOVA to PA via eal
+ "--iova-mode=pa" option can be used, IOVA_DC bus iommu scheme can also
+ result in IOVA as PA.
+
+ See :doc:`../prog_guide/lto` for more information:
Removed Items
@@ -1073,6 +1073,11 @@ rte_eal_init(int argc, char **argv)
*/
iova_mode = RTE_IOVA_VA;
RTE_LOG(DEBUG, EAL, "Physical addresses are unavailable, selecting IOVA as VA mode.\n");
+#if defined(RTE_LIBRTE_KNI) && LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)
+ } else if (rte_eal_check_module("rte_kni") == 1) {
+ iova_mode = RTE_IOVA_PA;
+ RTE_LOG(DEBUG, EAL, "KNI is loaded, selecting IOVA as PA mode for better KNI perfomance.\n");
+#endif
} else if (is_iommu_enabled()) {
/* we have an IOMMU, pick IOVA as VA mode */
iova_mode = RTE_IOVA_VA;
@@ -1085,8 +1090,10 @@ rte_eal_init(int argc, char **argv)
RTE_LOG(DEBUG, EAL, "IOMMU is not available, selecting IOVA as PA mode.\n");
}
}
-#ifdef RTE_LIBRTE_KNI
- /* Workaround for KNI which requires physical address to work */
+#if defined(RTE_LIBRTE_KNI) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
+ /* Workaround for KNI which requires physical address to work
+ * in kernels < 4.6
+ */
if (iova_mode == RTE_IOVA_VA &&
rte_eal_check_module("rte_kni") == 1) {
if (phys_addrs) {
@@ -10,6 +10,7 @@
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
+#include <linux/version.h>
#include <rte_spinlock.h>
#include <rte_string_fns.h>
@@ -97,10 +98,12 @@ static volatile int kni_fd = -1;
int
rte_kni_init(unsigned int max_kni_ifaces __rte_unused)
{
+#if KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE
if (rte_eal_iova_mode() != RTE_IOVA_PA) {
RTE_LOG(ERR, KNI, "KNI requires IOVA as PA\n");
return -1;
}
+#endif
/* Check FD and open */
if (kni_fd < 0) {
@@ -302,6 +305,8 @@ rte_kni_alloc(struct rte_mempool *pktmbuf_pool,
kni->group_id = conf->group_id;
kni->mbuf_size = conf->mbuf_size;
+ dev_info.iova_mode = (rte_eal_iova_mode() == RTE_IOVA_VA) ? 1 : 0;
+
ret = ioctl(kni_fd, RTE_KNI_IOCTL_CREATE, &dev_info);
if (ret < 0)
goto ioctl_fail;