+static volatile int kni_fd = -1;
+
+/* Shall be called before any allocation happens */
+int
+rte_kni_init(unsigned int max_kni_ifaces __rte_unused)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
+ 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) {
+ kni_fd = open("/dev/" KNI_DEVICE, O_RDWR);
+ if (kni_fd < 0) {
+ RTE_LOG(ERR, KNI,
+ "Can not open /dev/%s\n", KNI_DEVICE);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static struct rte_kni *
+__rte_kni_get(const char *name)
+{
+ struct rte_kni *kni;
+ struct rte_tailq_entry *te;
+ struct rte_kni_list *kni_list;
+
+ kni_list = RTE_TAILQ_CAST(rte_kni_tailq.head, rte_kni_list);
+
+ TAILQ_FOREACH(te, kni_list, next) {
+ kni = te->data;
+ if (strncmp(name, kni->name, RTE_KNI_NAMESIZE) == 0)
+ break;
+ }
+
+ if (te == NULL)
+ kni = NULL;
+
+ return kni;
+}
+
+static int
+kni_reserve_mz(struct rte_kni *kni)
+{
+ char mz_name[RTE_MEMZONE_NAMESIZE];
+
+ snprintf(mz_name, RTE_MEMZONE_NAMESIZE, KNI_TX_Q_MZ_NAME_FMT, kni->name);
+ kni->m_tx_q = rte_memzone_reserve(mz_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
+ KNI_MEM_CHECK(kni->m_tx_q == NULL, tx_q_fail);
+
+ snprintf(mz_name, RTE_MEMZONE_NAMESIZE, KNI_RX_Q_MZ_NAME_FMT, kni->name);
+ kni->m_rx_q = rte_memzone_reserve(mz_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
+ KNI_MEM_CHECK(kni->m_rx_q == NULL, rx_q_fail);
+
+ snprintf(mz_name, RTE_MEMZONE_NAMESIZE, KNI_ALLOC_Q_MZ_NAME_FMT, kni->name);
+ kni->m_alloc_q = rte_memzone_reserve(mz_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
+ KNI_MEM_CHECK(kni->m_alloc_q == NULL, alloc_q_fail);
+
+ snprintf(mz_name, RTE_MEMZONE_NAMESIZE, KNI_FREE_Q_MZ_NAME_FMT, kni->name);
+ kni->m_free_q = rte_memzone_reserve(mz_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
+ KNI_MEM_CHECK(kni->m_free_q == NULL, free_q_fail);
+
+ snprintf(mz_name, RTE_MEMZONE_NAMESIZE, KNI_REQ_Q_MZ_NAME_FMT, kni->name);
+ kni->m_req_q = rte_memzone_reserve(mz_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
+ KNI_MEM_CHECK(kni->m_req_q == NULL, req_q_fail);
+
+ snprintf(mz_name, RTE_MEMZONE_NAMESIZE, KNI_RESP_Q_MZ_NAME_FMT, kni->name);
+ kni->m_resp_q = rte_memzone_reserve(mz_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
+ KNI_MEM_CHECK(kni->m_resp_q == NULL, resp_q_fail);