From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id BD5BB42F9B; Tue, 1 Aug 2023 18:05:33 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 67E154325F; Tue, 1 Aug 2023 18:05:20 +0200 (CEST) Received: from mail-pf1-f169.google.com (mail-pf1-f169.google.com [209.85.210.169]) by mails.dpdk.org (Postfix) with ESMTP id D09F543258 for ; Tue, 1 Aug 2023 18:05:17 +0200 (CEST) Received: by mail-pf1-f169.google.com with SMTP id d2e1a72fcca58-686be3cbea0so4481163b3a.0 for ; Tue, 01 Aug 2023 09:05:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=networkplumber-org.20221208.gappssmtp.com; s=20221208; t=1690905916; x=1691510716; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=3AzivGpm5dE0hVCtNz9EI6SD/S3Iv0QKILW/MsL/Pdk=; b=KLpXrTL193vbT89qBElUOoGqqeIhdCUGALgPhgCfu4o70HNp7s+45IRj72SDsJXb2r a1KQO9P95bmjkmkvHF2byDDSHaAi9rw7PVRbOHNtwRu6M0E+qgk+OJ2uRIM6r2kKsJ3p TNGCJ7hvQj2X9xo3rZMBFbev8THI6Cl2wpqEMivWxrAJ74dUJmPrsd5rLZH14VXld8jb m/x2d/Oy+Qu4M/V8kYGW89+i2QKunNDtOAeo21sn52EZ/9zrleF1RMbzU4QcQNU1IcX6 nJHGpC0g51v4CZ6kCAEnMYkG5AXJbQEIcFsCVpAIGnzq4LFyWpATk2SgR6SU6jVAnP1l rLlQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1690905916; x=1691510716; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=3AzivGpm5dE0hVCtNz9EI6SD/S3Iv0QKILW/MsL/Pdk=; b=QyoStDEcreJGUdSpmSMf3u8wkbxwqZ8uo8nojUcYkPGse/hPsOqgRPPs2Fao3SfDG0 DrmzD7khtNsZDsCs4Vr9t+Oe13r2EvYxsbuGv+CNcaVJDNpmE3m9CBoqv7A9lyxHSL5K KGf8mWC3vhL/ESSc+/W2muxY+I0kp31RVmheQLHCZcAvJUVBgaZOsCGRF4FvCIe+4byV NZ8GtpdQjJDP+0LwtuSyZqV1HE5nLxJ7tDeYN9pbgIbRKftnXOgFGr/m4mLwYlI2GktO sPOvH0fEmYJqJzagdh5Y9KBKqYkPzNardA3UORy0bIPACL/c6T0+6zQI8IdXOzuMizWi ARnw== X-Gm-Message-State: ABy/qLYdeSiDdxCmq6DVawx+YSXzXnoOPf1D0rdx5nTNiI5H4tEL20bv eHB6hacMzFg6Nd6QgWOpa4TuYRvC9muVhtGyIi8pHw== X-Google-Smtp-Source: APBJJlGByihtsH/nMH0IbVAWzOmvP6Dg+o6xVHwCZQXH07nlmUYjEBvXPBBeDpi7GwDfTyf7F6KRAg== X-Received: by 2002:a17:90b:1bc6:b0:268:5aaf:fbe with SMTP id oa6-20020a17090b1bc600b002685aaf0fbemr17002591pjb.10.1690905914262; Tue, 01 Aug 2023 09:05:14 -0700 (PDT) Received: from hermes.local (204-195-127-207.wavecable.com. [204.195.127.207]) by smtp.gmail.com with ESMTPSA id li11-20020a170903294b00b001b89f6550d1sm10655939plb.16.2023.08.01.09.05.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Aug 2023 09:05:13 -0700 (PDT) From: Stephen Hemminger To: dev@dpdk.org Cc: Stephen Hemminger , Thomas Monjalon , Maxime Coquelin , Chenbo Xia , Anatoly Burakov , Cristian Dumitrescu , Nithin Dabilpuram , Kiran Kumar K , Sunil Kumar Kori , Satha Rao , Bruce Richardson Subject: [PATCH v2 2/2] kni: remove deprecated kernel network interface Date: Tue, 1 Aug 2023 09:05:00 -0700 Message-Id: <20230801160500.67480-3-stephen@networkplumber.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230801160500.67480-1-stephen@networkplumber.org> References: <20230801160500.67480-1-stephen@networkplumber.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org The KNI driver had design flaws such as calling userspace with kernel mutex held that made it prone to deadlock. The design also introduced security risks because the kernel driver trusted that the userspace (DPDK) kni interface. The kernel driver was never reviewed by the upstream kernel community and would never have been accepted. And since the Linux kernel API is not stable, it was a continual source of maintenance issues especially with distribution kernels. There are better ways to inject packets into the kernel such as virtio_user, tap and XDP drivers. All of these do not need out of tree kernel drivers. The deprecation was announced in 22.11 release; and users were directed to alternatives there. Signed-off-by: Stephen Hemminger --- MAINTAINERS | 10 - app/test/meson.build | 2 - app/test/test_kni.c | 740 --------------- doc/api/doxy-api-index.md | 2 - doc/api/doxy-api.conf.in | 1 - doc/guides/contributing/documentation.rst | 4 +- doc/guides/howto/flow_bifurcation.rst | 3 +- doc/guides/nics/index.rst | 1 - doc/guides/nics/kni.rst | 170 ---- doc/guides/nics/virtio.rst | 92 +- .../prog_guide/env_abstraction_layer.rst | 2 - doc/guides/prog_guide/glossary.rst | 3 - doc/guides/prog_guide/index.rst | 1 - .../prog_guide/kernel_nic_interface.rst | 423 --------- doc/guides/prog_guide/packet_framework.rst | 9 +- doc/guides/rel_notes/deprecation.rst | 9 +- doc/guides/rel_notes/release_23_11.rst | 2 + doc/guides/sample_app_ug/ip_pipeline.rst | 22 - drivers/net/cnxk/cnxk_ethdev.c | 2 +- drivers/net/kni/meson.build | 11 - drivers/net/kni/rte_eth_kni.c | 524 ----------- drivers/net/meson.build | 1 - examples/ip_pipeline/Makefile | 1 - examples/ip_pipeline/cli.c | 95 -- examples/ip_pipeline/examples/kni.cli | 69 -- examples/ip_pipeline/kni.c | 168 ---- examples/ip_pipeline/kni.h | 46 - examples/ip_pipeline/main.c | 10 - examples/ip_pipeline/meson.build | 1 - examples/ip_pipeline/pipeline.c | 57 -- examples/ip_pipeline/pipeline.h | 2 - kernel/linux/kni/Kbuild | 6 - kernel/linux/kni/compat.h | 157 ---- kernel/linux/kni/kni_dev.h | 137 --- kernel/linux/kni/kni_fifo.h | 87 -- kernel/linux/kni/kni_misc.c | 719 -------------- kernel/linux/kni/kni_net.c | 878 ------------------ kernel/linux/kni/meson.build | 41 - kernel/linux/meson.build | 2 +- lib/eal/common/eal_common_log.c | 1 - lib/eal/include/rte_log.h | 2 +- lib/eal/linux/eal.c | 19 - lib/kni/meson.build | 21 - lib/kni/rte_kni.c | 843 ----------------- lib/kni/rte_kni.h | 269 ------ lib/kni/rte_kni_common.h | 147 --- lib/kni/rte_kni_fifo.h | 117 --- lib/kni/version.map | 24 - lib/meson.build | 6 - lib/port/meson.build | 6 - lib/port/rte_port_kni.c | 515 ---------- lib/port/rte_port_kni.h | 63 -- lib/port/version.map | 3 - meson_options.txt | 2 +- 54 files changed, 14 insertions(+), 6534 deletions(-) delete mode 100644 app/test/test_kni.c delete mode 100644 doc/guides/nics/kni.rst delete mode 100644 doc/guides/prog_guide/kernel_nic_interface.rst delete mode 100644 drivers/net/kni/meson.build delete mode 100644 drivers/net/kni/rte_eth_kni.c delete mode 100644 examples/ip_pipeline/examples/kni.cli delete mode 100644 examples/ip_pipeline/kni.c delete mode 100644 examples/ip_pipeline/kni.h delete mode 100644 kernel/linux/kni/Kbuild delete mode 100644 kernel/linux/kni/compat.h delete mode 100644 kernel/linux/kni/kni_dev.h delete mode 100644 kernel/linux/kni/kni_fifo.h delete mode 100644 kernel/linux/kni/kni_misc.c delete mode 100644 kernel/linux/kni/kni_net.c delete mode 100644 kernel/linux/kni/meson.build delete mode 100644 lib/kni/meson.build delete mode 100644 lib/kni/rte_kni.c delete mode 100644 lib/kni/rte_kni.h delete mode 100644 lib/kni/rte_kni_common.h delete mode 100644 lib/kni/rte_kni_fifo.h delete mode 100644 lib/kni/version.map delete mode 100644 lib/port/rte_port_kni.c delete mode 100644 lib/port/rte_port_kni.h diff --git a/MAINTAINERS b/MAINTAINERS index dbb25211c367..6345e7f8a65d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -617,12 +617,6 @@ F: doc/guides/prog_guide/link_bonding_poll_mode_drv_lib.rst F: app/test/test_link_bonding* F: examples/bond/ -Linux KNI -F: kernel/linux/kni/ -F: lib/kni/ -F: doc/guides/prog_guide/kernel_nic_interface.rst -F: app/test/test_kni.c - Linux AF_PACKET M: John W. Linville F: drivers/net/af_packet/ @@ -1027,10 +1021,6 @@ F: drivers/net/tap/ F: doc/guides/nics/tap.rst F: doc/guides/nics/features/tap.ini -KNI PMD -F: drivers/net/kni/ -F: doc/guides/nics/kni.rst - Ring PMD M: Bruce Richardson F: drivers/net/ring/ diff --git a/app/test/meson.build b/app/test/meson.build index 90a2e350c7ae..66897c14a399 100644 --- a/app/test/meson.build +++ b/app/test/meson.build @@ -72,7 +72,6 @@ test_sources = files( 'test_ipsec.c', 'test_ipsec_sad.c', 'test_ipsec_perf.c', - 'test_kni.c', 'test_kvargs.c', 'test_lcores.c', 'test_logs.c', @@ -237,7 +236,6 @@ fast_tests = [ ['fbarray_autotest', true, true], ['hash_readwrite_func_autotest', false, true], ['ipsec_autotest', true, true], - ['kni_autotest', false, true], ['kvargs_autotest', true, true], ['member_autotest', true, true], ['power_cpufreq_autotest', false, true], diff --git a/app/test/test_kni.c b/app/test/test_kni.c deleted file mode 100644 index 4039da0b080c..000000000000 --- a/app/test/test_kni.c +++ /dev/null @@ -1,740 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation - */ - -#include "test.h" - -#include -#include -#include -#include -#if !defined(RTE_EXEC_ENV_LINUX) || !defined(RTE_LIB_KNI) - -static int -test_kni(void) -{ - printf("KNI not supported, skipping test\n"); - return TEST_SKIPPED; -} - -#else - -#include -#include - -#include -#include -#include -#include -#include - -#define NB_MBUF 8192 -#define MAX_PACKET_SZ 2048 -#define MBUF_DATA_SZ (MAX_PACKET_SZ + RTE_PKTMBUF_HEADROOM) -#define PKT_BURST_SZ 32 -#define MEMPOOL_CACHE_SZ PKT_BURST_SZ -#define SOCKET 0 -#define NB_RXD 1024 -#define NB_TXD 1024 -#define KNI_TIMEOUT_MS 5000 /* ms */ - -#define IFCONFIG "/sbin/ifconfig " -#define TEST_KNI_PORT "test_kni_port" -#define KNI_MODULE_PATH "/sys/module/rte_kni" -#define KNI_MODULE_PARAM_LO KNI_MODULE_PATH"/parameters/lo_mode" -#define KNI_TEST_MAX_PORTS 4 -/* The threshold number of mbufs to be transmitted or received. */ -#define KNI_NUM_MBUF_THRESHOLD 100 -static int kni_pkt_mtu = 0; - -struct test_kni_stats { - volatile uint64_t ingress; - volatile uint64_t egress; -}; - -static const struct rte_eth_rxconf rx_conf = { - .rx_thresh = { - .pthresh = 8, - .hthresh = 8, - .wthresh = 4, - }, - .rx_free_thresh = 0, -}; - -static const struct rte_eth_txconf tx_conf = { - .tx_thresh = { - .pthresh = 36, - .hthresh = 0, - .wthresh = 0, - }, - .tx_free_thresh = 0, - .tx_rs_thresh = 0, -}; - -static const struct rte_eth_conf port_conf = { - .txmode = { - .mq_mode = RTE_ETH_MQ_TX_NONE, - }, -}; - -static struct rte_kni_ops kni_ops = { - .change_mtu = NULL, - .config_network_if = NULL, - .config_mac_address = NULL, - .config_promiscusity = NULL, -}; - -static unsigned int lcore_main, lcore_ingress, lcore_egress; -static struct rte_kni *test_kni_ctx; -static struct test_kni_stats stats; - -static volatile uint32_t test_kni_processing_flag; - -static struct rte_mempool * -test_kni_create_mempool(void) -{ - struct rte_mempool * mp; - - mp = rte_mempool_lookup("kni_mempool"); - if (!mp) - mp = rte_pktmbuf_pool_create("kni_mempool", - NB_MBUF, - MEMPOOL_CACHE_SZ, 0, MBUF_DATA_SZ, - SOCKET); - - return mp; -} - -static struct rte_mempool * -test_kni_lookup_mempool(void) -{ - return rte_mempool_lookup("kni_mempool"); -} -/* Callback for request of changing MTU */ -static int -kni_change_mtu(uint16_t port_id, unsigned int new_mtu) -{ - printf("Change MTU of port %d to %u\n", port_id, new_mtu); - kni_pkt_mtu = new_mtu; - printf("Change MTU of port %d to %i successfully.\n", - port_id, kni_pkt_mtu); - return 0; -} - -static int -test_kni_link_change(void) -{ - int ret; - int pid; - - pid = fork(); - if (pid < 0) { - printf("Error: Failed to fork a process\n"); - return -1; - } - - if (pid == 0) { - printf("Starting KNI Link status change tests.\n"); - if (system(IFCONFIG TEST_KNI_PORT" up") == -1) { - ret = -1; - goto error; - } - - ret = rte_kni_update_link(test_kni_ctx, 1); - if (ret < 0) { - printf("Failed to change link state to Up ret=%d.\n", - ret); - goto error; - } - rte_delay_ms(1000); - printf("KNI: Set LINKUP, previous state=%d\n", ret); - - ret = rte_kni_update_link(test_kni_ctx, 0); - if (ret != 1) { - printf( - "Failed! Previous link state should be 1, returned %d.\n", - ret); - goto error; - } - rte_delay_ms(1000); - printf("KNI: Set LINKDOWN, previous state=%d\n", ret); - - ret = rte_kni_update_link(test_kni_ctx, 1); - if (ret != 0) { - printf( - "Failed! Previous link state should be 0, returned %d.\n", - ret); - goto error; - } - printf("KNI: Set LINKUP, previous state=%d\n", ret); - - ret = 0; - rte_delay_ms(1000); - -error: - if (system(IFCONFIG TEST_KNI_PORT" down") == -1) - ret = -1; - - printf("KNI: Link status change tests: %s.\n", - (ret == 0) ? "Passed" : "Failed"); - exit(ret); - } else { - int p_ret, status; - - while (1) { - p_ret = waitpid(pid, &status, WNOHANG); - if (p_ret != 0) { - if (WIFEXITED(status)) - return WEXITSTATUS(status); - return -1; - } - rte_delay_ms(10); - rte_kni_handle_request(test_kni_ctx); - } - } -} -/** - * This loop fully tests the basic functions of KNI. e.g. transmitting, - * receiving to, from kernel space, and kernel requests. - * - * This is the loop to transmit/receive mbufs to/from kernel interface with - * supported by KNI kernel module. The ingress lcore will allocate mbufs and - * transmit them to kernel space; while the egress lcore will receive the mbufs - * from kernel space and free them. - * On the main lcore, several commands will be run to check handling the - * kernel requests. And it will finally set the flag to exit the KNI - * transmitting/receiving to/from the kernel space. - * - * Note: To support this testing, the KNI kernel module needs to be insmodded - * in one of its loopback modes. - */ -static int -test_kni_loop(__rte_unused void *arg) -{ - int ret = 0; - unsigned nb_rx, nb_tx, num, i; - const unsigned lcore_id = rte_lcore_id(); - struct rte_mbuf *pkts_burst[PKT_BURST_SZ]; - - if (lcore_id == lcore_main) { - rte_delay_ms(KNI_TIMEOUT_MS); - /* tests of handling kernel request */ - if (system(IFCONFIG TEST_KNI_PORT" up") == -1) - ret = -1; - if (system(IFCONFIG TEST_KNI_PORT" mtu 1400") == -1) - ret = -1; - if (system(IFCONFIG TEST_KNI_PORT" down") == -1) - ret = -1; - rte_delay_ms(KNI_TIMEOUT_MS); - test_kni_processing_flag = 1; - } else if (lcore_id == lcore_ingress) { - struct rte_mempool *mp = test_kni_lookup_mempool(); - - if (mp == NULL) - return -1; - - while (1) { - if (test_kni_processing_flag) - break; - - for (nb_rx = 0; nb_rx < PKT_BURST_SZ; nb_rx++) { - pkts_burst[nb_rx] = rte_pktmbuf_alloc(mp); - if (!pkts_burst[nb_rx]) - break; - } - - num = rte_kni_tx_burst(test_kni_ctx, pkts_burst, - nb_rx); - stats.ingress += num; - rte_kni_handle_request(test_kni_ctx); - if (num < nb_rx) { - for (i = num; i < nb_rx; i++) { - rte_pktmbuf_free(pkts_burst[i]); - } - } - rte_delay_ms(10); - } - } else if (lcore_id == lcore_egress) { - while (1) { - if (test_kni_processing_flag) - break; - num = rte_kni_rx_burst(test_kni_ctx, pkts_burst, - PKT_BURST_SZ); - stats.egress += num; - for (nb_tx = 0; nb_tx < num; nb_tx++) - rte_pktmbuf_free(pkts_burst[nb_tx]); - rte_delay_ms(10); - } - } - - return ret; -} - -static int -test_kni_allocate_lcores(void) -{ - unsigned i, count = 0; - - lcore_main = rte_get_main_lcore(); - printf("main lcore: %u\n", lcore_main); - for (i = 0; i < RTE_MAX_LCORE; i++) { - if (count >=2 ) - break; - if (rte_lcore_is_enabled(i) && i != lcore_main) { - count ++; - if (count == 1) - lcore_ingress = i; - else if (count == 2) - lcore_egress = i; - } - } - printf("count: %u\n", count); - - return count == 2 ? 0 : -1; -} - -static int -test_kni_register_handler_mp(void) -{ -#define TEST_KNI_HANDLE_REQ_COUNT 10 /* 5s */ -#define TEST_KNI_HANDLE_REQ_INTERVAL 500 /* ms */ -#define TEST_KNI_MTU 1450 -#define TEST_KNI_MTU_STR " 1450" - int pid; - - pid = fork(); - if (pid < 0) { - printf("Failed to fork a process\n"); - return -1; - } else if (pid == 0) { - int i; - struct rte_kni *kni = rte_kni_get(TEST_KNI_PORT); - struct rte_kni_ops ops = { - .change_mtu = kni_change_mtu, - .config_network_if = NULL, - .config_mac_address = NULL, - .config_promiscusity = NULL, - }; - - if (!kni) { - printf("Failed to get KNI named %s\n", TEST_KNI_PORT); - exit(-1); - } - - kni_pkt_mtu = 0; - - /* Check with the invalid parameters */ - if (rte_kni_register_handlers(kni, NULL) == 0) { - printf("Unexpectedly register successfully " - "with NULL ops pointer\n"); - exit(-1); - } - if (rte_kni_register_handlers(NULL, &ops) == 0) { - printf("Unexpectedly register successfully " - "to NULL KNI device pointer\n"); - exit(-1); - } - - if (rte_kni_register_handlers(kni, &ops)) { - printf("Fail to register ops\n"); - exit(-1); - } - - /* Check registering again after it has been registered */ - if (rte_kni_register_handlers(kni, &ops) == 0) { - printf("Unexpectedly register successfully after " - "it has already been registered\n"); - exit(-1); - } - - /** - * Handle the request of setting MTU, - * with registered handlers. - */ - for (i = 0; i < TEST_KNI_HANDLE_REQ_COUNT; i++) { - rte_kni_handle_request(kni); - if (kni_pkt_mtu == TEST_KNI_MTU) - break; - rte_delay_ms(TEST_KNI_HANDLE_REQ_INTERVAL); - } - if (i >= TEST_KNI_HANDLE_REQ_COUNT) { - printf("MTU has not been set\n"); - exit(-1); - } - - kni_pkt_mtu = 0; - if (rte_kni_unregister_handlers(kni) < 0) { - printf("Fail to unregister ops\n"); - exit(-1); - } - - /* Check with invalid parameter */ - if (rte_kni_unregister_handlers(NULL) == 0) { - exit(-1); - } - - /** - * Handle the request of setting MTU, - * without registered handlers. - */ - for (i = 0; i < TEST_KNI_HANDLE_REQ_COUNT; i++) { - rte_kni_handle_request(kni); - if (kni_pkt_mtu != 0) - break; - rte_delay_ms(TEST_KNI_HANDLE_REQ_INTERVAL); - } - if (kni_pkt_mtu != 0) { - printf("MTU shouldn't be set\n"); - exit(-1); - } - - exit(0); - } else { - int p_ret, status; - - rte_delay_ms(1000); - if (system(IFCONFIG TEST_KNI_PORT " mtu" TEST_KNI_MTU_STR) - == -1) - return -1; - - rte_delay_ms(1000); - if (system(IFCONFIG TEST_KNI_PORT " mtu" TEST_KNI_MTU_STR) - == -1) - return -1; - - p_ret = wait(&status); - if (!WIFEXITED(status)) { - printf("Child process (%d) exit abnormally\n", p_ret); - return -1; - } - if (WEXITSTATUS(status) != 0) { - printf("Child process exit with failure\n"); - return -1; - } - } - - return 0; -} - -static int -test_kni_processing(uint16_t port_id, struct rte_mempool *mp) -{ - int ret = 0; - unsigned i; - struct rte_kni *kni; - struct rte_kni_conf conf; - struct rte_eth_dev_info info; - struct rte_kni_ops ops; - - if (!mp) - return -1; - - memset(&conf, 0, sizeof(conf)); - memset(&info, 0, sizeof(info)); - memset(&ops, 0, sizeof(ops)); - - ret = rte_eth_dev_info_get(port_id, &info); - if (ret != 0) { - printf("Error during getting device (port %u) info: %s\n", - port_id, strerror(-ret)); - return -1; - } - - snprintf(conf.name, sizeof(conf.name), TEST_KNI_PORT); - - /* core id 1 configured for kernel thread */ - conf.core_id = 1; - conf.force_bind = 1; - conf.mbuf_size = MAX_PACKET_SZ; - conf.group_id = port_id; - - ops = kni_ops; - ops.port_id = port_id; - - /* basic test of kni processing */ - kni = rte_kni_alloc(mp, &conf, &ops); - if (!kni) { - printf("fail to create kni\n"); - return -1; - } - - test_kni_ctx = kni; - test_kni_processing_flag = 0; - stats.ingress = 0; - stats.egress = 0; - - /** - * Check multiple processes support on - * registering/unregistering handlers. - */ - if (test_kni_register_handler_mp() < 0) { - printf("fail to check multiple process support\n"); - ret = -1; - goto fail_kni; - } - - ret = test_kni_link_change(); - if (ret != 0) - goto fail_kni; - - rte_eal_mp_remote_launch(test_kni_loop, NULL, CALL_MAIN); - RTE_LCORE_FOREACH_WORKER(i) { - if (rte_eal_wait_lcore(i) < 0) { - ret = -1; - goto fail_kni; - } - } - /** - * Check if the number of mbufs received from kernel space is equal - * to that of transmitted to kernel space - */ - if (stats.ingress < KNI_NUM_MBUF_THRESHOLD || - stats.egress < KNI_NUM_MBUF_THRESHOLD) { - printf("The ingress/egress number should not be " - "less than %u\n", (unsigned)KNI_NUM_MBUF_THRESHOLD); - ret = -1; - goto fail_kni; - } - - if (rte_kni_release(kni) < 0) { - printf("fail to release kni\n"); - return -1; - } - test_kni_ctx = NULL; - - /* test of reusing memzone */ - kni = rte_kni_alloc(mp, &conf, &ops); - if (!kni) { - printf("fail to create kni\n"); - return -1; - } - - /* Release the kni for following testing */ - if (rte_kni_release(kni) < 0) { - printf("fail to release kni\n"); - return -1; - } - - return ret; -fail_kni: - if (rte_kni_release(kni) < 0) { - printf("fail to release kni\n"); - ret = -1; - } - - return ret; -} - -static int -test_kni(void) -{ - int ret = -1; - uint16_t port_id; - struct rte_kni *kni; - struct rte_mempool *mp; - struct rte_kni_conf conf; - struct rte_eth_dev_info info; - struct rte_kni_ops ops; - FILE *fd; - DIR *dir; - char buf[16]; - - dir = opendir(KNI_MODULE_PATH); - if (!dir) { - if (errno == ENOENT) { - printf("Cannot run UT due to missing rte_kni module\n"); - return TEST_SKIPPED; - } - printf("opendir: %s", strerror(errno)); - return -1; - } - closedir(dir); - - /* Initialize KNI subsystem */ - ret = rte_kni_init(KNI_TEST_MAX_PORTS); - if (ret < 0) { - printf("fail to initialize KNI subsystem\n"); - return -1; - } - - if (test_kni_allocate_lcores() < 0) { - printf("No enough lcores for kni processing\n"); - return -1; - } - - mp = test_kni_create_mempool(); - if (!mp) { - printf("fail to create mempool for kni\n"); - return -1; - } - - /* configuring port 0 for the test is enough */ - port_id = 0; - ret = rte_eth_dev_configure(port_id, 1, 1, &port_conf); - if (ret < 0) { - printf("fail to configure port %d\n", port_id); - return -1; - } - - ret = rte_eth_rx_queue_setup(port_id, 0, NB_RXD, SOCKET, &rx_conf, mp); - if (ret < 0) { - printf("fail to setup rx queue for port %d\n", port_id); - return -1; - } - - ret = rte_eth_tx_queue_setup(port_id, 0, NB_TXD, SOCKET, &tx_conf); - if (ret < 0) { - printf("fail to setup tx queue for port %d\n", port_id); - return -1; - } - - ret = rte_eth_dev_start(port_id); - if (ret < 0) { - printf("fail to start port %d\n", port_id); - return -1; - } - ret = rte_eth_promiscuous_enable(port_id); - if (ret != 0) { - printf("fail to enable promiscuous mode for port %d: %s\n", - port_id, rte_strerror(-ret)); - return -1; - } - - /* basic test of kni processing */ - fd = fopen(KNI_MODULE_PARAM_LO, "r"); - if (fd == NULL) { - printf("fopen: %s", strerror(errno)); - return -1; - } - memset(&buf, 0, sizeof(buf)); - if (fgets(buf, sizeof(buf), fd)) { - if (!strncmp(buf, "lo_mode_fifo", strlen("lo_mode_fifo")) || - !strncmp(buf, "lo_mode_fifo_skb", - strlen("lo_mode_fifo_skb"))) { - ret = test_kni_processing(port_id, mp); - if (ret < 0) { - fclose(fd); - goto fail; - } - } else - printf("test_kni_processing skipped because of missing rte_kni module lo_mode argument\n"); - } - fclose(fd); - - /* test of allocating KNI with NULL mempool pointer */ - memset(&info, 0, sizeof(info)); - memset(&conf, 0, sizeof(conf)); - memset(&ops, 0, sizeof(ops)); - - ret = rte_eth_dev_info_get(port_id, &info); - if (ret != 0) { - printf("Error during getting device (port %u) info: %s\n", - port_id, strerror(-ret)); - return -1; - } - - conf.group_id = port_id; - conf.mbuf_size = MAX_PACKET_SZ; - - ops = kni_ops; - ops.port_id = port_id; - kni = rte_kni_alloc(NULL, &conf, &ops); - if (kni) { - ret = -1; - printf("unexpectedly creates kni successfully with NULL " - "mempool pointer\n"); - goto fail; - } - - /* test of allocating KNI without configurations */ - kni = rte_kni_alloc(mp, NULL, NULL); - if (kni) { - ret = -1; - printf("Unexpectedly allocate KNI device successfully " - "without configurations\n"); - goto fail; - } - - /* test of allocating KNI without a name */ - memset(&conf, 0, sizeof(conf)); - memset(&info, 0, sizeof(info)); - memset(&ops, 0, sizeof(ops)); - - ret = rte_eth_dev_info_get(port_id, &info); - if (ret != 0) { - printf("Error during getting device (port %u) info: %s\n", - port_id, strerror(-ret)); - ret = -1; - goto fail; - } - - conf.group_id = port_id; - conf.mbuf_size = MAX_PACKET_SZ; - - ops = kni_ops; - ops.port_id = port_id; - kni = rte_kni_alloc(mp, &conf, &ops); - if (kni) { - ret = -1; - printf("Unexpectedly allocate a KNI device successfully " - "without a name\n"); - goto fail; - } - - /* test of releasing NULL kni context */ - ret = rte_kni_release(NULL); - if (ret == 0) { - ret = -1; - printf("unexpectedly release kni successfully\n"); - goto fail; - } - - /* test of handling request on NULL device pointer */ - ret = rte_kni_handle_request(NULL); - if (ret == 0) { - ret = -1; - printf("Unexpectedly handle request on NULL device pointer\n"); - goto fail; - } - - /* test of getting KNI device with pointer to NULL */ - kni = rte_kni_get(NULL); - if (kni) { - ret = -1; - printf("Unexpectedly get a KNI device with " - "NULL name pointer\n"); - goto fail; - } - - /* test of getting KNI device with an zero length name string */ - memset(&conf, 0, sizeof(conf)); - kni = rte_kni_get(conf.name); - if (kni) { - ret = -1; - printf("Unexpectedly get a KNI device with " - "zero length name string\n"); - goto fail; - } - - /* test of getting KNI device with an invalid string name */ - memset(&conf, 0, sizeof(conf)); - snprintf(conf.name, sizeof(conf.name), "testing"); - kni = rte_kni_get(conf.name); - if (kni) { - ret = -1; - printf("Unexpectedly get a KNI device with " - "a never used name string\n"); - goto fail; - } - ret = 0; - -fail: - if (rte_eth_dev_stop(port_id) != 0) - printf("Failed to stop port %u\n", port_id); - - return ret; -} - -#endif - -REGISTER_TEST_COMMAND(kni_autotest, test_kni); diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index 5cd8c9de8105..fdeda139329e 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -43,7 +43,6 @@ The public API headers are grouped by topics: [bond](@ref rte_eth_bond.h), [vhost](@ref rte_vhost.h), [vdpa](@ref rte_vdpa.h), - [KNI](@ref rte_kni.h), [ixgbe](@ref rte_pmd_ixgbe.h), [i40e](@ref rte_pmd_i40e.h), [iavf](@ref rte_pmd_iavf.h), @@ -177,7 +176,6 @@ The public API headers are grouped by topics: [frag](@ref rte_port_frag.h), [reass](@ref rte_port_ras.h), [sched](@ref rte_port_sched.h), - [kni](@ref rte_port_kni.h), [src/sink](@ref rte_port_source_sink.h) * [table](@ref rte_table.h): [lpm IPv4](@ref rte_table_lpm.h), diff --git a/doc/api/doxy-api.conf.in b/doc/api/doxy-api.conf.in index 9a9c52e5569c..31885039c768 100644 --- a/doc/api/doxy-api.conf.in +++ b/doc/api/doxy-api.conf.in @@ -48,7 +48,6 @@ INPUT = @TOPDIR@/doc/api/doxy-api-index.md \ @TOPDIR@/lib/ip_frag \ @TOPDIR@/lib/ipsec \ @TOPDIR@/lib/jobstats \ - @TOPDIR@/lib/kni \ @TOPDIR@/lib/kvargs \ @TOPDIR@/lib/latencystats \ @TOPDIR@/lib/lpm \ diff --git a/doc/guides/contributing/documentation.rst b/doc/guides/contributing/documentation.rst index 7fcbb7fc43b2..38e184a130ee 100644 --- a/doc/guides/contributing/documentation.rst +++ b/doc/guides/contributing/documentation.rst @@ -94,8 +94,8 @@ added to by the developer. * **The Programmers Guide** - The Programmers Guide explains how the API components of DPDK such as the EAL, Memzone, Rings and the Hash Library work. - It also explains how some higher level functionality such as Packet Distributor, Packet Framework and KNI work. + The Programmers Guide explains how the API components of the DPDK such as the EAL, Memzone, Rings and the Hash Library work. + It also describes how some of the higher level functionality such as Packet Distributor and Packet Framework. It also shows the build system and explains how to add applications. The Programmers Guide should be expanded when new functionality is added to DPDK. diff --git a/doc/guides/howto/flow_bifurcation.rst b/doc/guides/howto/flow_bifurcation.rst index 838eb2a4cc89..554dd24c32c5 100644 --- a/doc/guides/howto/flow_bifurcation.rst +++ b/doc/guides/howto/flow_bifurcation.rst @@ -7,8 +7,7 @@ Flow Bifurcation How-to Guide Flow Bifurcation is a mechanism which uses hardware capable Ethernet devices to split traffic between Linux user space and kernel space. Since it is a hardware assisted feature this approach can provide line rate processing -capability. Other than :ref:`KNI `, the software is just required to -enable device configuration, there is no need to take care of the packet +capability. There is no need to take care of the packet movement during the traffic split. This can yield better performance with less CPU overhead. diff --git a/doc/guides/nics/index.rst b/doc/guides/nics/index.rst index 31296822e5ec..7bfcac880f44 100644 --- a/doc/guides/nics/index.rst +++ b/doc/guides/nics/index.rst @@ -43,7 +43,6 @@ Network Interface Controller Drivers ionic ipn3ke ixgbe - kni mana memif mlx4 diff --git a/doc/guides/nics/kni.rst b/doc/guides/nics/kni.rst deleted file mode 100644 index bd3033bb585c..000000000000 --- a/doc/guides/nics/kni.rst +++ /dev/null @@ -1,170 +0,0 @@ -.. SPDX-License-Identifier: BSD-3-Clause - Copyright(c) 2017 Intel Corporation. - -KNI Poll Mode Driver -====================== - -KNI PMD is wrapper to the :ref:`librte_kni ` library. - -This PMD enables using KNI without having a KNI specific application, -any forwarding application can use PMD interface for KNI. - -Sending packets to any DPDK controlled interface or sending to the -Linux networking stack will be transparent to the DPDK application. - -To create a KNI device ``net_kni#`` device name should be used, and this -will create ``kni#`` Linux virtual network interface. - -There is no physical device backend for the virtual KNI device. - -Packets sent to the KNI Linux interface will be received by the DPDK -application, and DPDK application may forward packets to a physical NIC -or to a virtual device (like another KNI interface or PCAP interface). - -To forward any traffic from physical NIC to the Linux networking stack, -an application should control a physical port and create one virtual KNI port, -and forward between two. - -Using this PMD requires KNI kernel module be inserted. - - -Usage ------ - -EAL ``--vdev`` argument can be used to create KNI device instance, like:: - - dpdk-testpmd --vdev=net_kni0 --vdev=net_kni1 -- -i - -Above command will create ``kni0`` and ``kni1`` Linux network interfaces, -those interfaces can be controlled by standard Linux tools. - -When testpmd forwarding starts, any packets sent to ``kni0`` interface -forwarded to the ``kni1`` interface and vice versa. - -There is no hard limit on number of interfaces that can be created. - - -Default interface configuration -------------------------------- - -``librte_kni`` can create Linux network interfaces with different features, -feature set controlled by a configuration struct, and KNI PMD uses a fixed -configuration: - - .. code-block:: console - - Interface name: kni# - force bind kernel thread to a core : NO - mbuf size: (rte_pktmbuf_data_room_size(pktmbuf_pool) - RTE_PKTMBUF_HEADROOM) - mtu: (conf.mbuf_size - RTE_ETHER_HDR_LEN) - -KNI control path is not supported with the PMD, since there is no physical -backend device by default. - - -Runtime Configuration ---------------------- - -``no_request_thread``, by default PMD creates a pthread for each KNI interface -to handle Linux network interface control commands, like ``ifconfig kni0 up`` - -With ``no_request_thread`` option, pthread is not created and control commands -not handled by PMD. - -By default request thread is enabled. And this argument should not be used -most of the time, unless this PMD used with customized DPDK application to handle -requests itself. - -Argument usage:: - - dpdk-testpmd --vdev "net_kni0,no_request_thread=1" -- -i - - -PMD log messages ----------------- - -If KNI kernel module (rte_kni.ko) not inserted, following error log printed:: - - "KNI: KNI subsystem has not been initialized. Invoke rte_kni_init() first" - - -PMD testing ------------ - -It is possible to test PMD quickly using KNI kernel module loopback feature: - -* Insert KNI kernel module with loopback support: - - .. code-block:: console - - insmod /kernel/linux/kni/rte_kni.ko lo_mode=lo_mode_fifo_skb - -* Start testpmd with no physical device but two KNI virtual devices: - - .. code-block:: console - - ./dpdk-testpmd --vdev net_kni0 --vdev net_kni1 -- -i - - .. code-block:: console - - ... - Configuring Port 0 (socket 0) - KNI: pci: 00:00:00 c580:b8 - Port 0: 1A:4A:5B:7C:A2:8C - Configuring Port 1 (socket 0) - KNI: pci: 00:00:00 600:b9 - Port 1: AE:95:21:07:93:DD - Checking link statuses... - Port 0 Link Up - speed 10000 Mbps - full-duplex - Port 1 Link Up - speed 10000 Mbps - full-duplex - Done - testpmd> - -* Observe Linux interfaces - - .. code-block:: console - - $ ifconfig kni0 && ifconfig kni1 - kni0: flags=4098 mtu 1500 - ether ae:8e:79:8e:9b:c8 txqueuelen 1000 (Ethernet) - RX packets 0 bytes 0 (0.0 B) - RX errors 0 dropped 0 overruns 0 frame 0 - TX packets 0 bytes 0 (0.0 B) - TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 - - kni1: flags=4098 mtu 1500 - ether 9e:76:43:53:3e:9b txqueuelen 1000 (Ethernet) - RX packets 0 bytes 0 (0.0 B) - RX errors 0 dropped 0 overruns 0 frame 0 - TX packets 0 bytes 0 (0.0 B) - TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 - - -* Start forwarding with tx_first: - - .. code-block:: console - - testpmd> start tx_first - -* Quit and check forwarding stats: - - .. code-block:: console - - testpmd> quit - Telling cores to stop... - Waiting for lcores to finish... - - ---------------------- Forward statistics for port 0 ---------------------- - RX-packets: 35637905 RX-dropped: 0 RX-total: 35637905 - TX-packets: 35637947 TX-dropped: 0 TX-total: 35637947 - ---------------------------------------------------------------------------- - - ---------------------- Forward statistics for port 1 ---------------------- - RX-packets: 35637915 RX-dropped: 0 RX-total: 35637915 - TX-packets: 35637937 TX-dropped: 0 TX-total: 35637937 - ---------------------------------------------------------------------------- - - +++++++++++++++ Accumulated forward statistics for all ports+++++++++++++++ - RX-packets: 71275820 RX-dropped: 0 RX-total: 71275820 - TX-packets: 71275884 TX-dropped: 0 TX-total: 71275884 - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ diff --git a/doc/guides/nics/virtio.rst b/doc/guides/nics/virtio.rst index f5e54a5e9cfd..ba6247170dbb 100644 --- a/doc/guides/nics/virtio.rst +++ b/doc/guides/nics/virtio.rst @@ -10,15 +10,12 @@ we provide a virtio Poll Mode Driver (PMD) as a software solution, comparing to for fast guest VM to guest VM communication and guest VM to host communication. Vhost is a kernel acceleration module for virtio qemu backend. -The DPDK extends kni to support vhost raw socket interface, -which enables vhost to directly read/ write packets from/to a physical port. -With this enhancement, virtio could achieve quite promising performance. For basic qemu-KVM installation and other Intel EM poll mode driver in guest VM, please refer to Chapter "Driver for VM Emulated Devices". In this chapter, we will demonstrate usage of virtio PMD with two backends, -standard qemu vhost back end and vhost kni back end. +standard qemu vhost back end. Virtio Implementation in DPDK ----------------------------- @@ -89,93 +86,6 @@ The following prerequisites apply: * When using legacy interface, ``SYS_RAWIO`` capability is required for ``iopl()`` call to enable access to PCI I/O ports. -Virtio with kni vhost Back End ------------------------------- - -This section demonstrates kni vhost back end example setup for Phy-VM Communication. - -.. _figure_host_vm_comms: - -.. figure:: img/host_vm_comms.* - - Host2VM Communication Example Using kni vhost Back End - - -Host2VM communication example - -#. Load the kni kernel module: - - .. code-block:: console - - insmod rte_kni.ko - - Other basic DPDK preparations like hugepage enabling, - UIO port binding are not listed here. - Please refer to the *DPDK Getting Started Guide* for detailed instructions. - -#. Launch the kni user application: - - .. code-block:: console - - /examples/dpdk-kni -l 0-3 -n 4 -- -p 0x1 -P --config="(0,1,3)" - - This command generates one network device vEth0 for physical port. - If specify more physical ports, the generated network device will be vEth1, vEth2, and so on. - - For each physical port, kni creates two user threads. - One thread loops to fetch packets from the physical NIC port into the kni receive queue. - The other user thread loops to send packets in the kni transmit queue. - - For each physical port, kni also creates a kernel thread that retrieves packets from the kni receive queue, - place them onto kni's raw socket's queue and wake up the vhost kernel thread to exchange packets with the virtio virt queue. - - For more details about kni, please refer to :ref:`kni`. - -#. Enable the kni raw socket functionality for the specified physical NIC port, - get the generated file descriptor and set it in the qemu command line parameter. - Always remember to set ioeventfd_on and vhost_on. - - Example: - - .. code-block:: console - - echo 1 > /sys/class/net/vEth0/sock_en - fd=`cat /sys/class/net/vEth0/sock_fd` - exec qemu-system-x86_64 -enable-kvm -cpu host \ - -m 2048 -smp 4 -name dpdk-test1-vm1 \ - -drive file=/data/DPDKVMS/dpdk-vm.img \ - -netdev tap, fd=$fd,id=mynet_kni, script=no,vhost=on \ - -device virtio-net-pci,netdev=mynet_kni,bus=pci.0,addr=0x3,ioeventfd=on \ - -vnc:1 -daemonize - - In the above example, virtio port 0 in the guest VM will be associated with vEth0, which in turns corresponds to a physical port, - which means received packets come from vEth0, and transmitted packets is sent to vEth0. - -#. In the guest, bind the virtio device to the uio_pci_generic kernel module and start the forwarding application. - When the virtio port in guest bursts Rx, it is getting packets from the - raw socket's receive queue. - When the virtio port bursts Tx, it is sending packet to the tx_q. - - .. code-block:: console - - modprobe uio - dpdk-hugepages.py --setup 1G - modprobe uio_pci_generic - ./usertools/dpdk-devbind.py -b uio_pci_generic 00:03.0 - - We use testpmd as the forwarding application in this example. - - .. figure:: img/console.* - - Running testpmd - -#. Use IXIA packet generator to inject a packet stream into the KNI physical port. - - The packet reception and transmission flow path is: - - IXIA packet generator->82599 PF->KNI Rx queue->KNI raw socket queue->Guest - VM virtio port 0 Rx burst->Guest VM virtio port 0 Tx burst-> KNI Tx queue - ->82599 PF-> IXIA packet generator Virtio with qemu virtio Back End -------------------------------- diff --git a/doc/guides/prog_guide/env_abstraction_layer.rst b/doc/guides/prog_guide/env_abstraction_layer.rst index 93c8a031be56..5d382fdd9032 100644 --- a/doc/guides/prog_guide/env_abstraction_layer.rst +++ b/doc/guides/prog_guide/env_abstraction_layer.rst @@ -610,8 +610,6 @@ devices would fail anyway. ``RTE_PCI_DRV_NEED_IOVA_AS_VA`` flag is used to dictate that this PCI driver can only work in RTE_IOVA_VA mode. - When the KNI kernel module is detected, RTE_IOVA_PA mode is preferred as a - performance penalty is expected in RTE_IOVA_VA mode. IOVA Mode Configuration ~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/guides/prog_guide/glossary.rst b/doc/guides/prog_guide/glossary.rst index fb0910ba5b3f..8d6349701e43 100644 --- a/doc/guides/prog_guide/glossary.rst +++ b/doc/guides/prog_guide/glossary.rst @@ -103,9 +103,6 @@ lcore A logical execution unit of the processor, sometimes called a *hardware thread*. -KNI - Kernel Network Interface - L1 Layer 1 diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst index c04847bfa148..2c47d9d010f4 100644 --- a/doc/guides/prog_guide/index.rst +++ b/doc/guides/prog_guide/index.rst @@ -53,7 +53,6 @@ Programmer's Guide pcapng_lib pdump_lib multi_proc_support - kernel_nic_interface thread_safety_dpdk_functions eventdev event_ethernet_rx_adapter diff --git a/doc/guides/prog_guide/kernel_nic_interface.rst b/doc/guides/prog_guide/kernel_nic_interface.rst deleted file mode 100644 index 392e5df75fcf..000000000000 --- a/doc/guides/prog_guide/kernel_nic_interface.rst +++ /dev/null @@ -1,423 +0,0 @@ -.. SPDX-License-Identifier: BSD-3-Clause - Copyright(c) 2010-2015 Intel Corporation. - -.. _kni: - -Kernel NIC Interface -==================== - -.. note:: - - KNI is deprecated and will be removed in future. - See :doc:`../rel_notes/deprecation`. - - :ref:`virtio_user_as_exception_path` alternative is the preferred way - for interfacing with the Linux network stack - as it is an in-kernel solution and has similar performance expectations. - -.. note:: - - KNI is disabled by default in the DPDK build. - To re-enable the library, remove 'kni' from the "disable_libs" meson option when configuring a build. - -The DPDK Kernel NIC Interface (KNI) allows userspace applications access to the Linux* control plane. - -KNI provides an interface with the kernel network stack -and allows management of DPDK ports using standard Linux net tools -such as ``ethtool``, ``iproute2`` and ``tcpdump``. - -The main use case of KNI is to get/receive exception packets from/to Linux network stack -while main datapath IO is done bypassing the networking stack. - -There are other alternatives to KNI, all are available in the upstream Linux: - -#. :ref:`virtio_user_as_exception_path` - -#. :doc:`../nics/tap` as wrapper to `Linux tun/tap - `_ - -The benefits of using the KNI against alternatives are: - -* Faster than existing Linux TUN/TAP interfaces - (by eliminating system calls and copy_to_user()/copy_from_user() operations. - -The disadvantages of the KNI are: - -* It is out-of-tree Linux kernel module - which makes updating and distributing the driver more difficult. - Most users end up building the KNI driver from source - which requires the packages and tools to build kernel modules. - -* As it shares memory between userspace and kernelspace, - and kernel part directly uses input provided by userspace, it is not safe. - This makes hard to upstream the module. - -* Requires dedicated kernel cores. - -* Only a subset of net devices control commands are supported by KNI. - -The components of an application using the DPDK Kernel NIC Interface are shown in :numref:`figure_kernel_nic_intf`. - -.. _figure_kernel_nic_intf: - -.. figure:: img/kernel_nic_intf.* - - Components of a DPDK KNI Application - - -The DPDK KNI Kernel Module --------------------------- - -The KNI kernel loadable module ``rte_kni`` provides the kernel interface -for DPDK applications. - -When the ``rte_kni`` module is loaded, it will create a device ``/dev/kni`` -that is used by the DPDK KNI API functions to control and communicate with -the kernel module. - -The ``rte_kni`` kernel module contains several optional parameters which -can be specified when the module is loaded to control its behavior: - -.. code-block:: console - - # modinfo rte_kni.ko - - parm: lo_mode: KNI loopback mode (default=lo_mode_none): - lo_mode_none Kernel loopback disabled - lo_mode_fifo Enable kernel loopback with fifo - lo_mode_fifo_skb Enable kernel loopback with fifo and skb buffer - (charp) - parm: kthread_mode: Kernel thread mode (default=single): - single Single kernel thread mode enabled. - multiple Multiple kernel thread mode enabled. - (charp) - parm: carrier: Default carrier state for KNI interface (default=off): - off Interfaces will be created with carrier state set to off. - on Interfaces will be created with carrier state set to on. - (charp) - parm: enable_bifurcated: Enable request processing support for - bifurcated drivers, which means releasing rtnl_lock before calling - userspace callback and supporting async requests (default=off): - on Enable request processing support for bifurcated drivers. - (charp) - parm: min_scheduling_interval: KNI thread min scheduling interval (default=100 microseconds) - (long) - parm: max_scheduling_interval: KNI thread max scheduling interval (default=200 microseconds) - (long) - - -Loading the ``rte_kni`` kernel module without any optional parameters is -the typical way a DPDK application gets packets into and out of the kernel -network stack. Without any parameters, only one kernel thread is created -for all KNI devices for packet receiving in kernel side, loopback mode is -disabled, and the default carrier state of KNI interfaces is set to *off*. - -.. code-block:: console - - # insmod /kernel/linux/kni/rte_kni.ko - -.. _kni_loopback_mode: - -Loopback Mode -~~~~~~~~~~~~~ - -For testing, the ``rte_kni`` kernel module can be loaded in loopback mode -by specifying the ``lo_mode`` parameter: - -.. code-block:: console - - # insmod /kernel/linux/kni/rte_kni.ko lo_mode=lo_mode_fifo - -The ``lo_mode_fifo`` loopback option will loop back ring enqueue/dequeue -operations in kernel space. - -.. code-block:: console - - # insmod /kernel/linux/kni/rte_kni.ko lo_mode=lo_mode_fifo_skb - -The ``lo_mode_fifo_skb`` loopback option will loop back ring enqueue/dequeue -operations and sk buffer copies in kernel space. - -If the ``lo_mode`` parameter is not specified, loopback mode is disabled. - -.. _kni_kernel_thread_mode: - -Kernel Thread Mode -~~~~~~~~~~~~~~~~~~ - -To provide flexibility of performance, the ``rte_kni`` KNI kernel module -can be loaded with the ``kthread_mode`` parameter. The ``rte_kni`` kernel -module supports two options: "single kernel thread" mode and "multiple -kernel thread" mode. - -Single kernel thread mode is enabled as follows: - -.. code-block:: console - - # insmod /kernel/linux/kni/rte_kni.ko kthread_mode=single - -This mode will create only one kernel thread for all KNI interfaces to -receive data on the kernel side. By default, this kernel thread is not -bound to any particular core, but the user can set the core affinity for -this kernel thread by setting the ``core_id`` and ``force_bind`` parameters -in ``struct rte_kni_conf`` when the first KNI interface is created: - -For optimum performance, the kernel thread should be bound to a core in -on the same socket as the DPDK lcores used in the application. - -The KNI kernel module can also be configured to start a separate kernel -thread for each KNI interface created by the DPDK application. Multiple -kernel thread mode is enabled as follows: - -.. code-block:: console - - # insmod /kernel/linux/kni/rte_kni.ko kthread_mode=multiple - -This mode will create a separate kernel thread for each KNI interface to -receive data on the kernel side. The core affinity of each ``kni_thread`` -kernel thread can be specified by setting the ``core_id`` and ``force_bind`` -parameters in ``struct rte_kni_conf`` when each KNI interface is created. - -Multiple kernel thread mode can provide scalable higher performance if -sufficient unused cores are available on the host system. - -If the ``kthread_mode`` parameter is not specified, the "single kernel -thread" mode is used. - -.. _kni_default_carrier_state: - -Default Carrier State -~~~~~~~~~~~~~~~~~~~~~ - -The default carrier state of KNI interfaces created by the ``rte_kni`` -kernel module is controlled via the ``carrier`` option when the module -is loaded. - -If ``carrier=off`` is specified, the kernel module will leave the carrier -state of the interface *down* when the interface is management enabled. -The DPDK application can set the carrier state of the KNI interface using the -``rte_kni_update_link()`` function. This is useful for DPDK applications -which require that the carrier state of the KNI interface reflect the -actual link state of the corresponding physical NIC port. - -If ``carrier=on`` is specified, the kernel module will automatically set -the carrier state of the interface to *up* when the interface is management -enabled. This is useful for DPDK applications which use the KNI interface as -a purely virtual interface that does not correspond to any physical hardware -and do not wish to explicitly set the carrier state of the interface with -``rte_kni_update_link()``. It is also useful for testing in loopback mode -where the NIC port may not be physically connected to anything. - -To set the default carrier state to *on*: - -.. code-block:: console - - # insmod /kernel/linux/kni/rte_kni.ko carrier=on - -To set the default carrier state to *off*: - -.. code-block:: console - - # insmod /kernel/linux/kni/rte_kni.ko carrier=off - -If the ``carrier`` parameter is not specified, the default carrier state -of KNI interfaces will be set to *off*. - -.. _kni_bifurcated_device_support: - -Bifurcated Device Support -~~~~~~~~~~~~~~~~~~~~~~~~~ - -User callbacks are executed while kernel module holds the ``rtnl`` lock, this -causes a deadlock when callbacks run control commands on another Linux kernel -network interface. - -Bifurcated devices has kernel network driver part and to prevent deadlock for -them ``enable_bifurcated`` is used. - -To enable bifurcated device support: - -.. code-block:: console - - # insmod /kernel/linux/kni/rte_kni.ko enable_bifurcated=on - -Enabling bifurcated device support releases ``rtnl`` lock before calling -callback and locks it back after callback. Also enables asynchronous request to -support callbacks that requires rtnl lock to work (interface down). - -KNI Kthread Scheduling -~~~~~~~~~~~~~~~~~~~~~~ - -The ``min_scheduling_interval`` and ``max_scheduling_interval`` parameters -control the rescheduling interval of the KNI kthreads. - -This might be useful if we have use cases in which we require improved -latency or performance for control plane traffic. - -The implementation is backed by Linux High Precision Timers, and uses ``usleep_range``. -Hence, it will have the same granularity constraints as this Linux subsystem. - -For Linux High Precision Timers, you can check the following resource: `Kernel Timers `_ - -To set the ``min_scheduling_interval`` to a value of 100 microseconds: - -.. code-block:: console - - # insmod /kernel/linux/kni/rte_kni.ko min_scheduling_interval=100 - -To set the ``max_scheduling_interval`` to a value of 200 microseconds: - -.. code-block:: console - - # insmod /kernel/linux/kni/rte_kni.ko max_scheduling_interval=200 - -If the ``min_scheduling_interval`` and ``max_scheduling_interval`` parameters are -not specified, the default interval limits will be set to *100* and *200* respectively. - -KNI Creation and Deletion -------------------------- - -Before any KNI interfaces can be created, the ``rte_kni`` kernel module must -be loaded into the kernel and configured with the ``rte_kni_init()`` function. - -The KNI interfaces are created by a DPDK application dynamically via the -``rte_kni_alloc()`` function. - -The ``struct rte_kni_conf`` structure contains fields which allow the -user to specify the interface name, set the MTU size, set an explicit or -random MAC address and control the affinity of the kernel Rx thread(s) -(both single and multi-threaded modes). -By default the KNI sample example gets the MTU from the matching device, -and in case of KNI PMD it is derived from mbuf buffer length. - -The ``struct rte_kni_ops`` structure contains pointers to functions to -handle requests from the ``rte_kni`` kernel module. These functions -allow DPDK applications to perform actions when the KNI interfaces are -manipulated by control commands or functions external to the application. - -For example, the DPDK application may wish to enabled/disable a physical -NIC port when a user enabled/disables a KNI interface with ``ip link set -[up|down] dev ``. The DPDK application can register a callback for -``config_network_if`` which will be called when the interface management -state changes. - -There are currently four callbacks for which the user can register -application functions: - -``config_network_if``: - - Called when the management state of the KNI interface changes. - For example, when the user runs ``ip link set [up|down] dev ``. - -``change_mtu``: - - Called when the user changes the MTU size of the KNI - interface. For example, when the user runs ``ip link set mtu - dev ``. - -``config_mac_address``: - - Called when the user changes the MAC address of the KNI interface. - For example, when the user runs ``ip link set address - dev ``. If the user sets this callback function to NULL, - but sets the ``port_id`` field to a value other than -1, a default - callback handler in the rte_kni library ``kni_config_mac_address()`` - will be called which calls ``rte_eth_dev_default_mac_addr_set()`` - on the specified ``port_id``. - -``config_promiscusity``: - - Called when the user changes the promiscuity state of the KNI - interface. For example, when the user runs ``ip link set promisc - [on|off] dev ``. If the user sets this callback function to - NULL, but sets the ``port_id`` field to a value other than -1, a default - callback handler in the rte_kni library ``kni_config_promiscusity()`` - will be called which calls ``rte_eth_promiscuous_()`` - on the specified ``port_id``. - -``config_allmulticast``: - - Called when the user changes the allmulticast state of the KNI interface. - For example, when the user runs ``ifconfig [-]allmulti``. If the - user sets this callback function to NULL, but sets the ``port_id`` field to - a value other than -1, a default callback handler in the rte_kni library - ``kni_config_allmulticast()`` will be called which calls - ``rte_eth_allmulticast_()`` on the specified ``port_id``. - -In order to run these callbacks, the application must periodically call -the ``rte_kni_handle_request()`` function. Any user callback function -registered will be called directly from ``rte_kni_handle_request()`` so -care must be taken to prevent deadlock and to not block any DPDK fastpath -tasks. Typically DPDK applications which use these callbacks will need -to create a separate thread or secondary process to periodically call -``rte_kni_handle_request()``. - -The KNI interfaces can be deleted by a DPDK application with -``rte_kni_release()``. All KNI interfaces not explicitly deleted will be -deleted when the ``/dev/kni`` device is closed, either explicitly with -``rte_kni_close()`` or when the DPDK application is closed. - -DPDK mbuf Flow --------------- - -To minimize the amount of DPDK code running in kernel space, the mbuf mempool is managed in userspace only. -The kernel module will be aware of mbufs, -but all mbuf allocation and free operations will be handled by the DPDK application only. - -:numref:`figure_pkt_flow_kni` shows a typical scenario with packets sent in both directions. - -.. _figure_pkt_flow_kni: - -.. figure:: img/pkt_flow_kni.* - - Packet Flow via mbufs in the DPDK KNI - - -Use Case: Ingress ------------------ - -On the DPDK RX side, the mbuf is allocated by the PMD in the RX thread context. -This thread will enqueue the mbuf in the rx_q FIFO, -and the next pointers in mbuf-chain will convert to physical address. -The KNI thread will poll all KNI active devices for the rx_q. -If an mbuf is dequeued, it will be converted to a sk_buff and sent to the net stack via netif_rx(). -The dequeued mbuf must be freed, so the same pointer is sent back in the free_q FIFO, -and next pointers must convert back to virtual address if exists before put in the free_q FIFO. - -The RX thread, in the same main loop, polls this FIFO and frees the mbuf after dequeuing it. -The address conversion of the next pointer is to prevent the chained mbuf -in different hugepage segments from causing kernel crash. - -Use Case: Egress ----------------- - -For packet egress the DPDK application must first enqueue several mbufs to create an mbuf cache on the kernel side. - -The packet is received from the Linux net stack, by calling the kni_net_tx() callback. -The mbuf is dequeued (without waiting due the cache) and filled with data from sk_buff. -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, 10, 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 -------- - -Ethtool is a Linux-specific tool with corresponding support in the kernel. -The current version of kni provides minimal ethtool functionality -including querying version and link state. It does not support link -control, statistics, or dumping device registers. diff --git a/doc/guides/prog_guide/packet_framework.rst b/doc/guides/prog_guide/packet_framework.rst index 3d4e3b66cc5c..ebc69d8c3e75 100644 --- a/doc/guides/prog_guide/packet_framework.rst +++ b/doc/guides/prog_guide/packet_framework.rst @@ -87,18 +87,15 @@ Port Types | | | management and hierarchical scheduling according to pre-defined SLAs. | | | | | +---+------------------+---------------------------------------------------------------------------------------+ - | 6 | KNI | Send/receive packets to/from Linux kernel space. | - | | | | - +---+------------------+---------------------------------------------------------------------------------------+ - | 7 | Source | Input port used as packet generator. Similar to Linux kernel /dev/zero character | + | 6 | Source | Input port used as packet generator. Similar to Linux kernel /dev/zero character | | | | device. | | | | | +---+------------------+---------------------------------------------------------------------------------------+ - | 8 | Sink | Output port used to drop all input packets. Similar to Linux kernel /dev/null | + | 7 | Sink | Output port used to drop all input packets. Similar to Linux kernel /dev/null | | | | character device. | | | | | +---+------------------+---------------------------------------------------------------------------------------+ - | 9 | Sym_crypto | Output port used to extract DPDK Cryptodev operations from a fixed offset of the | + | 8 | Sym_crypto | Output port used to extract DPDK Cryptodev operations from a fixed offset of the | | | | packet and then enqueue to the Cryptodev PMD. Input port used to dequeue the | | | | Cryptodev operations from the Cryptodev PMD and then retrieve the packets from them. | +---+------------------+---------------------------------------------------------------------------------------+ diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst index ce5a8f0361cb..bb5d23c87669 100644 --- a/doc/guides/rel_notes/deprecation.rst +++ b/doc/guides/rel_notes/deprecation.rst @@ -35,7 +35,7 @@ Deprecation Notices which also added support for standard atomics (Ref: https://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html) -* build: Enabling deprecated libraries (``kni``) +* build: Enabling deprecated libraries won't be possible anymore through the use of the ``disable_libs`` build option. A new build option for deprecated libraries will be introduced instead. @@ -78,13 +78,6 @@ Deprecation Notices ``__atomic_thread_fence`` must be used for patches that need to be merged in 20.08 onwards. This change will not introduce any performance degradation. -* kni: The KNI kernel module and library are not recommended for use by new - applications - other technologies such as virtio-user are recommended instead. - Following the DPDK technical board - `decision `_ - and `refinement `_, - the KNI kernel module, library and PMD will be removed from the DPDK 23.11 release. - * lib: will fix extending some enum/define breaking the ABI. There are multiple samples in DPDK that enum/define terminated with a ``.*MAX.*`` value which is used by iterators, and arrays holding these values are sized with this diff --git a/doc/guides/rel_notes/release_23_11.rst b/doc/guides/rel_notes/release_23_11.rst index 9d96dbdcd302..0d5c4a60d020 100644 --- a/doc/guides/rel_notes/release_23_11.rst +++ b/doc/guides/rel_notes/release_23_11.rst @@ -70,6 +70,8 @@ Removed Items * flow_classify: Removed flow classification library and examples. +* kni: Removed the Kernel Network Interface (KNI) library and driver. + API Changes ----------- diff --git a/doc/guides/sample_app_ug/ip_pipeline.rst b/doc/guides/sample_app_ug/ip_pipeline.rst index b521d3b8be20..f30ac5e19db7 100644 --- a/doc/guides/sample_app_ug/ip_pipeline.rst +++ b/doc/guides/sample_app_ug/ip_pipeline.rst @@ -164,15 +164,6 @@ Examples | | | | 8. Pipeline table rule add default | | | | | 9. Pipeline table rule add | +-----------------------+----------------------+----------------+------------------------------------+ - | KNI | Stub | Forward | 1. Mempool create | - | | | | 2. Link create | - | | | | 3. Pipeline create | - | | | | 4. Pipeline port in/out | - | | | | 5. Pipeline table | - | | | | 6. Pipeline port in table | - | | | | 7. Pipeline enable | - | | | | 8. Pipeline table rule add | - +-----------------------+----------------------+----------------+------------------------------------+ | Firewall | ACL | Allow/Drop | 1. Mempool create | | | | | 2. Link create | | | * Key = n-tuple | | 3. Pipeline create | @@ -297,17 +288,6 @@ Tap tap -Kni -~~~ - - Create kni port :: - - kni - link - mempool - [thread ] - - Cryptodev ~~~~~~~~~ @@ -366,7 +346,6 @@ Create pipeline input port :: | swq | tmgr | tap mempool mtu - | kni | source mempool file bpp [action ] [disabled] @@ -379,7 +358,6 @@ Create pipeline output port :: | swq | tmgr | tap - | kni | sink [file pkts ] Create pipeline table :: diff --git a/drivers/net/cnxk/cnxk_ethdev.c b/drivers/net/cnxk/cnxk_ethdev.c index 4b98faa72980..01b707b6c4ac 100644 --- a/drivers/net/cnxk/cnxk_ethdev.c +++ b/drivers/net/cnxk/cnxk_ethdev.c @@ -1130,7 +1130,7 @@ nix_set_nop_rxtx_function(struct rte_eth_dev *eth_dev) { /* These dummy functions are required for supporting * some applications which reconfigure queues without - * stopping tx burst and rx burst threads(eg kni app) + * stopping tx burst and rx burst threads. * When the queues context is saved, txq/rxqs are released * which caused app crash since rx/tx burst is still * on different lcores diff --git a/drivers/net/kni/meson.build b/drivers/net/kni/meson.build deleted file mode 100644 index 2acc98969426..000000000000 --- a/drivers/net/kni/meson.build +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2018 Intel Corporation - -if is_windows - build = false - reason = 'not supported on Windows' - subdir_done() -endif - -deps += 'kni' -sources = files('rte_eth_kni.c') diff --git a/drivers/net/kni/rte_eth_kni.c b/drivers/net/kni/rte_eth_kni.c deleted file mode 100644 index c0e1f8db409e..000000000000 --- a/drivers/net/kni/rte_eth_kni.c +++ /dev/null @@ -1,524 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2017 Intel Corporation - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -/* Only single queue supported */ -#define KNI_MAX_QUEUE_PER_PORT 1 - -#define MAX_KNI_PORTS 8 - -#define KNI_ETHER_MTU(mbuf_size) \ - ((mbuf_size) - RTE_ETHER_HDR_LEN) /**< Ethernet MTU. */ - -#define ETH_KNI_NO_REQUEST_THREAD_ARG "no_request_thread" -static const char * const valid_arguments[] = { - ETH_KNI_NO_REQUEST_THREAD_ARG, - NULL -}; - -struct eth_kni_args { - int no_request_thread; -}; - -struct pmd_queue_stats { - uint64_t pkts; - uint64_t bytes; -}; - -struct pmd_queue { - struct pmd_internals *internals; - struct rte_mempool *mb_pool; - - struct pmd_queue_stats rx; - struct pmd_queue_stats tx; -}; - -struct pmd_internals { - struct rte_kni *kni; - uint16_t port_id; - int is_kni_started; - - pthread_t thread; - int stop_thread; - int no_request_thread; - - struct rte_ether_addr eth_addr; - - struct pmd_queue rx_queues[KNI_MAX_QUEUE_PER_PORT]; - struct pmd_queue tx_queues[KNI_MAX_QUEUE_PER_PORT]; -}; - -static const struct rte_eth_link pmd_link = { - .link_speed = RTE_ETH_SPEED_NUM_10G, - .link_duplex = RTE_ETH_LINK_FULL_DUPLEX, - .link_status = RTE_ETH_LINK_DOWN, - .link_autoneg = RTE_ETH_LINK_FIXED, -}; -static int is_kni_initialized; - -RTE_LOG_REGISTER_DEFAULT(eth_kni_logtype, NOTICE); - -#define PMD_LOG(level, fmt, args...) \ - rte_log(RTE_LOG_ ## level, eth_kni_logtype, \ - "%s(): " fmt "\n", __func__, ##args) -static uint16_t -eth_kni_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs) -{ - struct pmd_queue *kni_q = q; - struct rte_kni *kni = kni_q->internals->kni; - uint16_t nb_pkts; - int i; - - nb_pkts = rte_kni_rx_burst(kni, bufs, nb_bufs); - for (i = 0; i < nb_pkts; i++) - bufs[i]->port = kni_q->internals->port_id; - - kni_q->rx.pkts += nb_pkts; - - return nb_pkts; -} - -static uint16_t -eth_kni_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs) -{ - struct pmd_queue *kni_q = q; - struct rte_kni *kni = kni_q->internals->kni; - uint16_t nb_pkts; - - nb_pkts = rte_kni_tx_burst(kni, bufs, nb_bufs); - - kni_q->tx.pkts += nb_pkts; - - return nb_pkts; -} - -static void * -kni_handle_request(void *param) -{ - struct pmd_internals *internals = param; -#define MS 1000 - - while (!internals->stop_thread) { - rte_kni_handle_request(internals->kni); - usleep(500 * MS); - } - - return param; -} - -static int -eth_kni_start(struct rte_eth_dev *dev) -{ - struct pmd_internals *internals = dev->data->dev_private; - uint16_t port_id = dev->data->port_id; - struct rte_mempool *mb_pool; - struct rte_kni_conf conf = {{0}}; - const char *name = dev->device->name + 4; /* remove net_ */ - - mb_pool = internals->rx_queues[0].mb_pool; - strlcpy(conf.name, name, RTE_KNI_NAMESIZE); - conf.force_bind = 0; - conf.group_id = port_id; - conf.mbuf_size = - rte_pktmbuf_data_room_size(mb_pool) - RTE_PKTMBUF_HEADROOM; - conf.mtu = KNI_ETHER_MTU(conf.mbuf_size); - - internals->kni = rte_kni_alloc(mb_pool, &conf, NULL); - if (internals->kni == NULL) { - PMD_LOG(ERR, - "Fail to create kni interface for port: %d", - port_id); - return -1; - } - - return 0; -} - -static int -eth_kni_dev_start(struct rte_eth_dev *dev) -{ - struct pmd_internals *internals = dev->data->dev_private; - int ret; - - if (internals->is_kni_started == 0) { - ret = eth_kni_start(dev); - if (ret) - return -1; - internals->is_kni_started = 1; - } - - if (internals->no_request_thread == 0) { - internals->stop_thread = 0; - - ret = rte_ctrl_thread_create(&internals->thread, - "kni_handle_req", NULL, - kni_handle_request, internals); - if (ret) { - PMD_LOG(ERR, - "Fail to create kni request thread"); - return -1; - } - } - - dev->data->dev_link.link_status = 1; - - return 0; -} - -static int -eth_kni_dev_stop(struct rte_eth_dev *dev) -{ - struct pmd_internals *internals = dev->data->dev_private; - int ret; - - if (internals->no_request_thread == 0 && internals->stop_thread == 0) { - internals->stop_thread = 1; - - ret = pthread_cancel(internals->thread); - if (ret) - PMD_LOG(ERR, "Can't cancel the thread"); - - ret = pthread_join(internals->thread, NULL); - if (ret) - PMD_LOG(ERR, "Can't join the thread"); - } - - dev->data->dev_link.link_status = 0; - dev->data->dev_started = 0; - - return 0; -} - -static int -eth_kni_close(struct rte_eth_dev *eth_dev) -{ - struct pmd_internals *internals; - int ret; - - if (rte_eal_process_type() != RTE_PROC_PRIMARY) - return 0; - - ret = eth_kni_dev_stop(eth_dev); - if (ret) - PMD_LOG(WARNING, "Not able to stop kni for %s", - eth_dev->data->name); - - /* mac_addrs must not be freed alone because part of dev_private */ - eth_dev->data->mac_addrs = NULL; - - internals = eth_dev->data->dev_private; - ret = rte_kni_release(internals->kni); - if (ret) - PMD_LOG(WARNING, "Not able to release kni for %s", - eth_dev->data->name); - - return ret; -} - -static int -eth_kni_dev_configure(struct rte_eth_dev *dev __rte_unused) -{ - return 0; -} - -static int -eth_kni_dev_info(struct rte_eth_dev *dev __rte_unused, - struct rte_eth_dev_info *dev_info) -{ - dev_info->max_mac_addrs = 1; - dev_info->max_rx_pktlen = UINT32_MAX; - dev_info->max_rx_queues = KNI_MAX_QUEUE_PER_PORT; - dev_info->max_tx_queues = KNI_MAX_QUEUE_PER_PORT; - dev_info->min_rx_bufsize = 0; - - return 0; -} - -static int -eth_kni_rx_queue_setup(struct rte_eth_dev *dev, - uint16_t rx_queue_id, - uint16_t nb_rx_desc __rte_unused, - unsigned int socket_id __rte_unused, - const struct rte_eth_rxconf *rx_conf __rte_unused, - struct rte_mempool *mb_pool) -{ - struct pmd_internals *internals = dev->data->dev_private; - struct pmd_queue *q; - - q = &internals->rx_queues[rx_queue_id]; - q->internals = internals; - q->mb_pool = mb_pool; - - dev->data->rx_queues[rx_queue_id] = q; - - return 0; -} - -static int -eth_kni_tx_queue_setup(struct rte_eth_dev *dev, - uint16_t tx_queue_id, - uint16_t nb_tx_desc __rte_unused, - unsigned int socket_id __rte_unused, - const struct rte_eth_txconf *tx_conf __rte_unused) -{ - struct pmd_internals *internals = dev->data->dev_private; - struct pmd_queue *q; - - q = &internals->tx_queues[tx_queue_id]; - q->internals = internals; - - dev->data->tx_queues[tx_queue_id] = q; - - return 0; -} - -static int -eth_kni_link_update(struct rte_eth_dev *dev __rte_unused, - int wait_to_complete __rte_unused) -{ - return 0; -} - -static int -eth_kni_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) -{ - unsigned long rx_packets_total = 0, rx_bytes_total = 0; - unsigned long tx_packets_total = 0, tx_bytes_total = 0; - struct rte_eth_dev_data *data = dev->data; - unsigned int i, num_stats; - struct pmd_queue *q; - - num_stats = RTE_MIN((unsigned int)RTE_ETHDEV_QUEUE_STAT_CNTRS, - data->nb_rx_queues); - for (i = 0; i < num_stats; i++) { - q = data->rx_queues[i]; - stats->q_ipackets[i] = q->rx.pkts; - stats->q_ibytes[i] = q->rx.bytes; - rx_packets_total += stats->q_ipackets[i]; - rx_bytes_total += stats->q_ibytes[i]; - } - - num_stats = RTE_MIN((unsigned int)RTE_ETHDEV_QUEUE_STAT_CNTRS, - data->nb_tx_queues); - for (i = 0; i < num_stats; i++) { - q = data->tx_queues[i]; - stats->q_opackets[i] = q->tx.pkts; - stats->q_obytes[i] = q->tx.bytes; - tx_packets_total += stats->q_opackets[i]; - tx_bytes_total += stats->q_obytes[i]; - } - - stats->ipackets = rx_packets_total; - stats->ibytes = rx_bytes_total; - stats->opackets = tx_packets_total; - stats->obytes = tx_bytes_total; - - return 0; -} - -static int -eth_kni_stats_reset(struct rte_eth_dev *dev) -{ - struct rte_eth_dev_data *data = dev->data; - struct pmd_queue *q; - unsigned int i; - - for (i = 0; i < data->nb_rx_queues; i++) { - q = data->rx_queues[i]; - q->rx.pkts = 0; - q->rx.bytes = 0; - } - for (i = 0; i < data->nb_tx_queues; i++) { - q = data->tx_queues[i]; - q->tx.pkts = 0; - q->tx.bytes = 0; - } - - return 0; -} - -static const struct eth_dev_ops eth_kni_ops = { - .dev_start = eth_kni_dev_start, - .dev_stop = eth_kni_dev_stop, - .dev_close = eth_kni_close, - .dev_configure = eth_kni_dev_configure, - .dev_infos_get = eth_kni_dev_info, - .rx_queue_setup = eth_kni_rx_queue_setup, - .tx_queue_setup = eth_kni_tx_queue_setup, - .link_update = eth_kni_link_update, - .stats_get = eth_kni_stats_get, - .stats_reset = eth_kni_stats_reset, -}; - -static struct rte_eth_dev * -eth_kni_create(struct rte_vdev_device *vdev, - struct eth_kni_args *args, - unsigned int numa_node) -{ - struct pmd_internals *internals; - struct rte_eth_dev_data *data; - struct rte_eth_dev *eth_dev; - - PMD_LOG(INFO, "Creating kni ethdev on numa socket %u", - numa_node); - - /* reserve an ethdev entry */ - eth_dev = rte_eth_vdev_allocate(vdev, sizeof(*internals)); - if (!eth_dev) - return NULL; - - internals = eth_dev->data->dev_private; - internals->port_id = eth_dev->data->port_id; - data = eth_dev->data; - data->nb_rx_queues = 1; - data->nb_tx_queues = 1; - data->dev_link = pmd_link; - data->mac_addrs = &internals->eth_addr; - data->promiscuous = 1; - data->all_multicast = 1; - data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS; - - rte_eth_random_addr(internals->eth_addr.addr_bytes); - - eth_dev->dev_ops = ð_kni_ops; - - internals->no_request_thread = args->no_request_thread; - - return eth_dev; -} - -static int -kni_init(void) -{ - int ret; - - if (is_kni_initialized == 0) { - ret = rte_kni_init(MAX_KNI_PORTS); - if (ret < 0) - return ret; - } - - is_kni_initialized++; - - return 0; -} - -static int -eth_kni_kvargs_process(struct eth_kni_args *args, const char *params) -{ - struct rte_kvargs *kvlist; - - kvlist = rte_kvargs_parse(params, valid_arguments); - if (kvlist == NULL) - return -1; - - memset(args, 0, sizeof(struct eth_kni_args)); - - if (rte_kvargs_count(kvlist, ETH_KNI_NO_REQUEST_THREAD_ARG) == 1) - args->no_request_thread = 1; - - rte_kvargs_free(kvlist); - - return 0; -} - -static int -eth_kni_probe(struct rte_vdev_device *vdev) -{ - struct rte_eth_dev *eth_dev; - struct eth_kni_args args; - const char *name; - const char *params; - int ret; - - name = rte_vdev_device_name(vdev); - params = rte_vdev_device_args(vdev); - PMD_LOG(INFO, "Initializing eth_kni for %s", name); - - if (rte_eal_process_type() == RTE_PROC_SECONDARY) { - eth_dev = rte_eth_dev_attach_secondary(name); - if (!eth_dev) { - PMD_LOG(ERR, "Failed to probe %s", name); - return -1; - } - /* TODO: request info from primary to set up Rx and Tx */ - eth_dev->dev_ops = ð_kni_ops; - eth_dev->device = &vdev->device; - rte_eth_dev_probing_finish(eth_dev); - return 0; - } - - ret = eth_kni_kvargs_process(&args, params); - if (ret < 0) - return ret; - - ret = kni_init(); - if (ret < 0) - return ret; - - eth_dev = eth_kni_create(vdev, &args, rte_socket_id()); - if (eth_dev == NULL) - goto kni_uninit; - - eth_dev->rx_pkt_burst = eth_kni_rx; - eth_dev->tx_pkt_burst = eth_kni_tx; - - rte_eth_dev_probing_finish(eth_dev); - return 0; - -kni_uninit: - is_kni_initialized--; - if (is_kni_initialized == 0) - rte_kni_close(); - return -1; -} - -static int -eth_kni_remove(struct rte_vdev_device *vdev) -{ - struct rte_eth_dev *eth_dev; - const char *name; - int ret; - - name = rte_vdev_device_name(vdev); - PMD_LOG(INFO, "Un-Initializing eth_kni for %s", name); - - /* find the ethdev entry */ - eth_dev = rte_eth_dev_allocated(name); - if (eth_dev != NULL) { - if (rte_eal_process_type() != RTE_PROC_PRIMARY) { - ret = eth_kni_dev_stop(eth_dev); - if (ret != 0) - return ret; - return rte_eth_dev_release_port(eth_dev); - } - eth_kni_close(eth_dev); - rte_eth_dev_release_port(eth_dev); - } - - is_kni_initialized--; - if (is_kni_initialized == 0) - rte_kni_close(); - - return 0; -} - -static struct rte_vdev_driver eth_kni_drv = { - .probe = eth_kni_probe, - .remove = eth_kni_remove, -}; - -RTE_PMD_REGISTER_VDEV(net_kni, eth_kni_drv); -RTE_PMD_REGISTER_PARAM_STRING(net_kni, ETH_KNI_NO_REQUEST_THREAD_ARG "="); diff --git a/drivers/net/meson.build b/drivers/net/meson.build index f68bbc27a784..bd38b533c573 100644 --- a/drivers/net/meson.build +++ b/drivers/net/meson.build @@ -35,7 +35,6 @@ drivers = [ 'ionic', 'ipn3ke', 'ixgbe', - 'kni', 'mana', 'memif', 'mlx4', diff --git a/examples/ip_pipeline/Makefile b/examples/ip_pipeline/Makefile index 785c7ee38ce5..bc5e0a9f1800 100644 --- a/examples/ip_pipeline/Makefile +++ b/examples/ip_pipeline/Makefile @@ -8,7 +8,6 @@ APP = ip_pipeline SRCS-y := action.c SRCS-y += cli.c SRCS-y += conn.c -SRCS-y += kni.c SRCS-y += link.c SRCS-y += main.c SRCS-y += mempool.c diff --git a/examples/ip_pipeline/cli.c b/examples/ip_pipeline/cli.c index c918f30e06f3..e8269ea90c11 100644 --- a/examples/ip_pipeline/cli.c +++ b/examples/ip_pipeline/cli.c @@ -14,7 +14,6 @@ #include "cli.h" #include "cryptodev.h" -#include "kni.h" #include "link.h" #include "mempool.h" #include "parser.h" @@ -728,65 +727,6 @@ cmd_tap(char **tokens, } } -static const char cmd_kni_help[] = -"kni \n" -" link \n" -" mempool \n" -" [thread ]\n"; - -static void -cmd_kni(char **tokens, - uint32_t n_tokens, - char *out, - size_t out_size) -{ - struct kni_params p; - char *name; - struct kni *kni; - - memset(&p, 0, sizeof(p)); - if ((n_tokens != 6) && (n_tokens != 8)) { - snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); - return; - } - - name = tokens[1]; - - if (strcmp(tokens[2], "link") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "link"); - return; - } - - p.link_name = tokens[3]; - - if (strcmp(tokens[4], "mempool") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mempool"); - return; - } - - p.mempool_name = tokens[5]; - - if (n_tokens == 8) { - if (strcmp(tokens[6], "thread") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "thread"); - return; - } - - if (parser_read_uint32(&p.thread_id, tokens[7]) != 0) { - snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); - return; - } - - p.force_bind = 1; - } else - p.force_bind = 0; - - kni = kni_create(name, &p); - if (kni == NULL) { - snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); - return; - } -} static const char cmd_cryptodev_help[] = "cryptodev \n" @@ -1541,7 +1481,6 @@ static const char cmd_pipeline_port_in_help[] = " | swq \n" " | tmgr \n" " | tap mempool mtu \n" -" | kni \n" " | source mempool file bpp \n" " | cryptodev rxq \n" " [action ]\n" @@ -1664,18 +1603,6 @@ cmd_pipeline_port_in(char **tokens, } t0 += 6; - } else if (strcmp(tokens[t0], "kni") == 0) { - if (n_tokens < t0 + 2) { - snprintf(out, out_size, MSG_ARG_MISMATCH, - "pipeline port in kni"); - return; - } - - p.type = PORT_IN_KNI; - - p.dev_name = tokens[t0 + 1]; - - t0 += 2; } else if (strcmp(tokens[t0], "source") == 0) { if (n_tokens < t0 + 6) { snprintf(out, out_size, MSG_ARG_MISMATCH, @@ -1781,7 +1708,6 @@ static const char cmd_pipeline_port_out_help[] = " | swq \n" " | tmgr \n" " | tap \n" -" | kni \n" " | sink [file pkts ]\n" " | cryptodev txq offset \n"; @@ -1873,16 +1799,6 @@ cmd_pipeline_port_out(char **tokens, p.type = PORT_OUT_TAP; - p.dev_name = tokens[7]; - } else if (strcmp(tokens[6], "kni") == 0) { - if (n_tokens != 8) { - snprintf(out, out_size, MSG_ARG_MISMATCH, - "pipeline port out kni"); - return; - } - - p.type = PORT_OUT_KNI; - p.dev_name = tokens[7]; } else if (strcmp(tokens[6], "sink") == 0) { if ((n_tokens != 7) && (n_tokens != 11)) { @@ -6038,7 +5954,6 @@ cmd_help(char **tokens, uint32_t n_tokens, char *out, size_t out_size) "\ttmgr subport\n" "\ttmgr subport pipe\n" "\ttap\n" - "\tkni\n" "\tport in action profile\n" "\ttable action profile\n" "\tpipeline\n" @@ -6124,11 +6039,6 @@ cmd_help(char **tokens, uint32_t n_tokens, char *out, size_t out_size) return; } - if (strcmp(tokens[0], "kni") == 0) { - snprintf(out, out_size, "\n%s\n", cmd_kni_help); - return; - } - if (strcmp(tokens[0], "cryptodev") == 0) { snprintf(out, out_size, "\n%s\n", cmd_cryptodev_help); return; @@ -6436,11 +6346,6 @@ cli_process(char *in, char *out, size_t out_size) return; } - if (strcmp(tokens[0], "kni") == 0) { - cmd_kni(tokens, n_tokens, out, out_size); - return; - } - if (strcmp(tokens[0], "cryptodev") == 0) { cmd_cryptodev(tokens, n_tokens, out, out_size); return; diff --git a/examples/ip_pipeline/examples/kni.cli b/examples/ip_pipeline/examples/kni.cli deleted file mode 100644 index 143834093d4d..000000000000 --- a/examples/ip_pipeline/examples/kni.cli +++ /dev/null @@ -1,69 +0,0 @@ -; SPDX-License-Identifier: BSD-3-Clause -; Copyright(c) 2010-2018 Intel Corporation - -; _______________ ______________________ -; | | KNI0 | | -; LINK0 RXQ0 --->|...............|------->|--+ | -; | | KNI1 | | br0 | -; LINK1 TXQ0 <---|...............|<-------|<-+ | -; | | | Linux Kernel | -; | PIPELINE0 | | Network Stack | -; | | KNI1 | | -; LINK1 RXQ0 --->|...............|------->|--+ | -; | | KNI0 | | br0 | -; LINK0 TXQ0 <---|...............|<-------|<-+ | -; |_______________| |______________________| -; -; Insert Linux kernel KNI module: -; [Linux]$ insmod rte_kni.ko -; -; Configure Linux kernel bridge between KNI0 and KNI1 interfaces: -; [Linux]$ brctl addbr br0 -; [Linux]$ brctl addif br0 KNI0 -; [Linux]$ brctl addif br0 KNI1 -; [Linux]$ ifconfig br0 up -; [Linux]$ ifconfig KNI0 up -; [Linux]$ ifconfig KNI1 up -; -; Monitor packet forwarding performed by Linux kernel between KNI0 and KNI1: -; [Linux]$ tcpdump -i KNI0 -; [Linux]$ tcpdump -i KNI1 - -mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0 - -link LINK0 dev 0000:02:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on -link LINK1 dev 0000:02:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on - -kni KNI0 link LINK0 mempool MEMPOOL0 -kni KNI1 link LINK1 mempool MEMPOOL0 - -table action profile AP0 ipv4 offset 270 fwd - -pipeline PIPELINE0 period 10 offset_port_id 0 cpu 0 - -pipeline PIPELINE0 port in bsz 32 link LINK0 rxq 0 -pipeline PIPELINE0 port in bsz 32 kni KNI1 -pipeline PIPELINE0 port in bsz 32 link LINK1 rxq 0 -pipeline PIPELINE0 port in bsz 32 kni KNI0 - -pipeline PIPELINE0 port out bsz 32 kni KNI0 -pipeline PIPELINE0 port out bsz 32 link LINK1 txq 0 -pipeline PIPELINE0 port out bsz 32 kni KNI1 -pipeline PIPELINE0 port out bsz 32 link LINK0 txq 0 - -pipeline PIPELINE0 table match stub action AP0 -pipeline PIPELINE0 table match stub action AP0 -pipeline PIPELINE0 table match stub action AP0 -pipeline PIPELINE0 table match stub action AP0 - -pipeline PIPELINE0 port in 0 table 0 -pipeline PIPELINE0 port in 1 table 1 -pipeline PIPELINE0 port in 2 table 2 -pipeline PIPELINE0 port in 3 table 3 - -thread 1 pipeline PIPELINE0 enable - -pipeline PIPELINE0 table 0 rule add match default action fwd port 0 -pipeline PIPELINE0 table 1 rule add match default action fwd port 1 -pipeline PIPELINE0 table 2 rule add match default action fwd port 2 -pipeline PIPELINE0 table 3 rule add match default action fwd port 3 diff --git a/examples/ip_pipeline/kni.c b/examples/ip_pipeline/kni.c deleted file mode 100644 index cd02c3947827..000000000000 --- a/examples/ip_pipeline/kni.c +++ /dev/null @@ -1,168 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2018 Intel Corporation - */ - -#include -#include - -#include -#include - -#include "kni.h" -#include "mempool.h" -#include "link.h" - -static struct kni_list kni_list; - -#ifndef KNI_MAX -#define KNI_MAX 16 -#endif - -int -kni_init(void) -{ - TAILQ_INIT(&kni_list); - -#ifdef RTE_LIB_KNI - rte_kni_init(KNI_MAX); -#endif - - return 0; -} - -struct kni * -kni_find(const char *name) -{ - struct kni *kni; - - if (name == NULL) - return NULL; - - TAILQ_FOREACH(kni, &kni_list, node) - if (strcmp(kni->name, name) == 0) - return kni; - - return NULL; -} - -#ifndef RTE_LIB_KNI - -struct kni * -kni_create(const char *name __rte_unused, - struct kni_params *params __rte_unused) -{ - return NULL; -} - -void -kni_handle_request(void) -{ - return; -} - -#else - -static int -kni_config_network_interface(uint16_t port_id, uint8_t if_up) -{ - int ret = 0; - - if (!rte_eth_dev_is_valid_port(port_id)) - return -EINVAL; - - ret = (if_up) ? - rte_eth_dev_set_link_up(port_id) : - rte_eth_dev_set_link_down(port_id); - - return ret; -} - -static int -kni_change_mtu(uint16_t port_id, unsigned int new_mtu) -{ - int ret; - - if (!rte_eth_dev_is_valid_port(port_id)) - return -EINVAL; - - if (new_mtu > RTE_ETHER_MAX_LEN) - return -EINVAL; - - /* Set new MTU */ - ret = rte_eth_dev_set_mtu(port_id, new_mtu); - if (ret < 0) - return ret; - - return 0; -} - -struct kni * -kni_create(const char *name, struct kni_params *params) -{ - struct rte_eth_dev_info dev_info; - struct rte_kni_conf kni_conf; - struct rte_kni_ops kni_ops; - struct kni *kni; - struct mempool *mempool; - struct link *link; - struct rte_kni *k; - int ret; - - /* Check input params */ - if ((name == NULL) || - kni_find(name) || - (params == NULL)) - return NULL; - - mempool = mempool_find(params->mempool_name); - link = link_find(params->link_name); - if ((mempool == NULL) || - (link == NULL)) - return NULL; - - /* Resource create */ - ret = rte_eth_dev_info_get(link->port_id, &dev_info); - if (ret != 0) - return NULL; - - memset(&kni_conf, 0, sizeof(kni_conf)); - strlcpy(kni_conf.name, name, RTE_KNI_NAMESIZE); - kni_conf.force_bind = params->force_bind; - kni_conf.core_id = params->thread_id; - kni_conf.group_id = link->port_id; - kni_conf.mbuf_size = mempool->buffer_size; - - memset(&kni_ops, 0, sizeof(kni_ops)); - kni_ops.port_id = link->port_id; - kni_ops.config_network_if = kni_config_network_interface; - kni_ops.change_mtu = kni_change_mtu; - - k = rte_kni_alloc(mempool->m, &kni_conf, &kni_ops); - if (k == NULL) - return NULL; - - /* Node allocation */ - kni = calloc(1, sizeof(struct kni)); - if (kni == NULL) - return NULL; - - /* Node fill in */ - strlcpy(kni->name, name, sizeof(kni->name)); - kni->k = k; - - /* Node add to list */ - TAILQ_INSERT_TAIL(&kni_list, kni, node); - - return kni; -} - -void -kni_handle_request(void) -{ - struct kni *kni; - - TAILQ_FOREACH(kni, &kni_list, node) - rte_kni_handle_request(kni->k); -} - -#endif diff --git a/examples/ip_pipeline/kni.h b/examples/ip_pipeline/kni.h deleted file mode 100644 index 118f48df73d8..000000000000 --- a/examples/ip_pipeline/kni.h +++ /dev/null @@ -1,46 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2018 Intel Corporation - */ - -#ifndef _INCLUDE_KNI_H_ -#define _INCLUDE_KNI_H_ - -#include -#include - -#ifdef RTE_LIB_KNI -#include -#endif - -#include "common.h" - -struct kni { - TAILQ_ENTRY(kni) node; - char name[NAME_SIZE]; -#ifdef RTE_LIB_KNI - struct rte_kni *k; -#endif -}; - -TAILQ_HEAD(kni_list, kni); - -int -kni_init(void); - -struct kni * -kni_find(const char *name); - -struct kni_params { - const char *link_name; - const char *mempool_name; - int force_bind; - uint32_t thread_id; -}; - -struct kni * -kni_create(const char *name, struct kni_params *params); - -void -kni_handle_request(void); - -#endif /* _INCLUDE_KNI_H_ */ diff --git a/examples/ip_pipeline/main.c b/examples/ip_pipeline/main.c index e35d9bce3984..663f538f024a 100644 --- a/examples/ip_pipeline/main.c +++ b/examples/ip_pipeline/main.c @@ -14,7 +14,6 @@ #include "cli.h" #include "conn.h" -#include "kni.h" #include "cryptodev.h" #include "link.h" #include "mempool.h" @@ -205,13 +204,6 @@ main(int argc, char **argv) return status; } - /* KNI */ - status = kni_init(); - if (status) { - printf("Error: KNI initialization failed (%d)\n", status); - return status; - } - /* Sym Crypto */ status = cryptodev_init(); if (status) { @@ -264,7 +256,5 @@ main(int argc, char **argv) conn_poll_for_conn(conn); conn_poll_for_msg(conn); - - kni_handle_request(); } } diff --git a/examples/ip_pipeline/meson.build b/examples/ip_pipeline/meson.build index 57f522c24cf9..68049157e429 100644 --- a/examples/ip_pipeline/meson.build +++ b/examples/ip_pipeline/meson.build @@ -18,7 +18,6 @@ sources = files( 'cli.c', 'conn.c', 'cryptodev.c', - 'kni.c', 'link.c', 'main.c', 'mempool.c', diff --git a/examples/ip_pipeline/pipeline.c b/examples/ip_pipeline/pipeline.c index 7ebabcae984d..63352257c6e9 100644 --- a/examples/ip_pipeline/pipeline.c +++ b/examples/ip_pipeline/pipeline.c @@ -11,9 +11,6 @@ #include #include -#ifdef RTE_LIB_KNI -#include -#endif #include #include #include @@ -28,9 +25,6 @@ #include #include -#ifdef RTE_LIB_KNI -#include "kni.h" -#endif #include "link.h" #include "mempool.h" #include "pipeline.h" @@ -160,9 +154,6 @@ pipeline_port_in_create(const char *pipeline_name, struct rte_port_ring_reader_params ring; struct rte_port_sched_reader_params sched; struct rte_port_fd_reader_params fd; -#ifdef RTE_LIB_KNI - struct rte_port_kni_reader_params kni; -#endif struct rte_port_source_params source; struct rte_port_sym_crypto_reader_params sym_crypto; } pp; @@ -264,22 +255,6 @@ pipeline_port_in_create(const char *pipeline_name, break; } -#ifdef RTE_LIB_KNI - case PORT_IN_KNI: - { - struct kni *kni; - - kni = kni_find(params->dev_name); - if (kni == NULL) - return -1; - - pp.kni.kni = kni->k; - - p.ops = &rte_port_kni_reader_ops; - p.arg_create = &pp.kni; - break; - } -#endif case PORT_IN_SOURCE: { @@ -404,9 +379,6 @@ pipeline_port_out_create(const char *pipeline_name, struct rte_port_ring_writer_params ring; struct rte_port_sched_writer_params sched; struct rte_port_fd_writer_params fd; -#ifdef RTE_LIB_KNI - struct rte_port_kni_writer_params kni; -#endif struct rte_port_sink_params sink; struct rte_port_sym_crypto_writer_params sym_crypto; } pp; @@ -415,9 +387,6 @@ pipeline_port_out_create(const char *pipeline_name, struct rte_port_ethdev_writer_nodrop_params ethdev; struct rte_port_ring_writer_nodrop_params ring; struct rte_port_fd_writer_nodrop_params fd; -#ifdef RTE_LIB_KNI - struct rte_port_kni_writer_nodrop_params kni; -#endif struct rte_port_sym_crypto_writer_nodrop_params sym_crypto; } pp_nodrop; @@ -537,32 +506,6 @@ pipeline_port_out_create(const char *pipeline_name, break; } -#ifdef RTE_LIB_KNI - case PORT_OUT_KNI: - { - struct kni *kni; - - kni = kni_find(params->dev_name); - if (kni == NULL) - return -1; - - pp.kni.kni = kni->k; - pp.kni.tx_burst_sz = params->burst_size; - - pp_nodrop.kni.kni = kni->k; - pp_nodrop.kni.tx_burst_sz = params->burst_size; - pp_nodrop.kni.n_retries = params->n_retries; - - if (params->retry == 0) { - p.ops = &rte_port_kni_writer_ops; - p.arg_create = &pp.kni; - } else { - p.ops = &rte_port_kni_writer_nodrop_ops; - p.arg_create = &pp_nodrop.kni; - } - break; - } -#endif case PORT_OUT_SINK: { diff --git a/examples/ip_pipeline/pipeline.h b/examples/ip_pipeline/pipeline.h index 4d2ee29a54c7..083d5e852421 100644 --- a/examples/ip_pipeline/pipeline.h +++ b/examples/ip_pipeline/pipeline.h @@ -25,7 +25,6 @@ enum port_in_type { PORT_IN_SWQ, PORT_IN_TMGR, PORT_IN_TAP, - PORT_IN_KNI, PORT_IN_SOURCE, PORT_IN_CRYPTODEV, }; @@ -67,7 +66,6 @@ enum port_out_type { PORT_OUT_SWQ, PORT_OUT_TMGR, PORT_OUT_TAP, - PORT_OUT_KNI, PORT_OUT_SINK, PORT_OUT_CRYPTODEV, }; diff --git a/kernel/linux/kni/Kbuild b/kernel/linux/kni/Kbuild deleted file mode 100644 index e5452d6c00db..000000000000 --- a/kernel/linux/kni/Kbuild +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2018 Luca Boccassi - -ccflags-y := $(MODULE_CFLAGS) -obj-m := rte_kni.o -rte_kni-y := $(patsubst $(src)/%.c,%.o,$(wildcard $(src)/*.c)) diff --git a/kernel/linux/kni/compat.h b/kernel/linux/kni/compat.h deleted file mode 100644 index 8beb67046577..000000000000 --- a/kernel/linux/kni/compat.h +++ /dev/null @@ -1,157 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Minimal wrappers to allow compiling kni on older kernels. - */ - -#include - -#ifndef RHEL_RELEASE_VERSION -#define RHEL_RELEASE_VERSION(a, b) (((a) << 8) + (b)) -#endif - -/* SuSE version macro is the same as Linux kernel version */ -#ifndef SLE_VERSION -#define SLE_VERSION(a, b, c) KERNEL_VERSION(a, b, c) -#endif -#ifdef CONFIG_SUSE_KERNEL -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 57)) -/* SLES12SP3 is at least 4.4.57+ based */ -#define SLE_VERSION_CODE SLE_VERSION(12, 3, 0) -#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 28)) -/* SLES12 is at least 3.12.28+ based */ -#define SLE_VERSION_CODE SLE_VERSION(12, 0, 0) -#elif ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 61)) && \ - (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0))) -/* SLES11 SP3 is at least 3.0.61+ based */ -#define SLE_VERSION_CODE SLE_VERSION(11, 3, 0) -#elif (LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 32)) -/* SLES11 SP1 is 2.6.32 based */ -#define SLE_VERSION_CODE SLE_VERSION(11, 1, 0) -#elif (LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 27)) -/* SLES11 GA is 2.6.27 based */ -#define SLE_VERSION_CODE SLE_VERSION(11, 0, 0) -#endif /* LINUX_VERSION_CODE == KERNEL_VERSION(x,y,z) */ -#endif /* CONFIG_SUSE_KERNEL */ -#ifndef SLE_VERSION_CODE -#define SLE_VERSION_CODE 0 -#endif /* SLE_VERSION_CODE */ - - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) && \ - (!(defined(RHEL_RELEASE_CODE) && \ - RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6, 4))) - -#define kstrtoul strict_strtoul - -#endif /* < 2.6.39 */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33) -#define HAVE_SIMPLIFIED_PERNET_OPERATIONS -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) -#define sk_sleep(s) ((s)->sk_sleep) -#else -#define HAVE_SOCKET_WQ -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0) -#define HAVE_STATIC_SOCK_MAP_FD -#else -#define kni_sock_map_fd(s) sock_map_fd(s, 0) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) -#define HAVE_CHANGE_CARRIER_CB -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) -#define ether_addr_copy(dst, src) memcpy(dst, src, ETH_ALEN) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) -#define HAVE_IOV_ITER_MSGHDR -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0) -#define HAVE_KIOCB_MSG_PARAM -#define HAVE_REBUILD_HEADER -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) -#define HAVE_SK_ALLOC_KERN_PARAM -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) || \ - (defined(RHEL_RELEASE_CODE) && \ - RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7, 4)) || \ - (SLE_VERSION_CODE && SLE_VERSION_CODE == SLE_VERSION(12, 3, 0)) -#define HAVE_TRANS_START_HELPER -#endif - -/* - * KNI uses NET_NAME_UNKNOWN macro to select correct version of alloc_netdev() - * For old kernels just backported the commit that enables the macro - * (685343fc3ba6) but still uses old API, it is required to undefine macro to - * select correct version of API, this is safe since KNI doesn't use the value. - * This fix is specific to RedHat/CentOS kernels. - */ -#if (defined(RHEL_RELEASE_CODE) && \ - (RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6, 8)) && \ - (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34))) -#undef NET_NAME_UNKNOWN -#endif - -/* - * RHEL has two different version with different kernel version: - * 3.10 is for AMD, Intel, IBM POWER7 and POWER8; - * 4.14 is for ARM and IBM POWER9 - */ -#if (defined(RHEL_RELEASE_CODE) && \ - (RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7, 5)) && \ - (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8, 0)) && \ - (LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0))) -#define ndo_change_mtu ndo_change_mtu_rh74 -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0) -#define HAVE_MAX_MTU_PARAM -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) -#define HAVE_SIGNAL_FUNCTIONS_OWN_HEADER -#endif - -/* - * iova to kva mapping support can be provided since 4.6.0, but required - * kernel version increased to >= 4.10.0 because of the updates in - * get_user_pages_remote() kernel API - */ -#if KERNEL_VERSION(4, 10, 0) <= LINUX_VERSION_CODE -#define HAVE_IOVA_TO_KVA_MAPPING_SUPPORT -#endif - -#if KERNEL_VERSION(5, 6, 0) <= LINUX_VERSION_CODE || \ - (defined(RHEL_RELEASE_CODE) && \ - RHEL_RELEASE_VERSION(8, 3) <= RHEL_RELEASE_CODE) || \ - (defined(CONFIG_SUSE_KERNEL) && defined(HAVE_ARG_TX_QUEUE)) -#define HAVE_TX_TIMEOUT_TXQUEUE -#endif - -#if KERNEL_VERSION(5, 9, 0) > LINUX_VERSION_CODE -#define HAVE_TSK_IN_GUP -#endif - -#if KERNEL_VERSION(5, 15, 0) <= LINUX_VERSION_CODE -#define HAVE_ETH_HW_ADDR_SET -#endif - -#if KERNEL_VERSION(5, 18, 0) > LINUX_VERSION_CODE && \ - (!(defined(RHEL_RELEASE_CODE) && \ - RHEL_RELEASE_VERSION(9, 1) <= RHEL_RELEASE_CODE)) -#define HAVE_NETIF_RX_NI -#endif - -#if KERNEL_VERSION(6, 5, 0) > LINUX_VERSION_CODE -#define HAVE_VMA_IN_GUP -#endif diff --git a/kernel/linux/kni/kni_dev.h b/kernel/linux/kni/kni_dev.h deleted file mode 100644 index 975379825b2d..000000000000 --- a/kernel/linux/kni/kni_dev.h +++ /dev/null @@ -1,137 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright(c) 2010-2014 Intel Corporation. - */ - -#ifndef _KNI_DEV_H_ -#define _KNI_DEV_H_ - -#ifdef pr_fmt -#undef pr_fmt -#endif -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define KNI_VERSION "1.0" - -#include "compat.h" - -#include -#include -#ifdef HAVE_SIGNAL_FUNCTIONS_OWN_HEADER -#include -#else -#include -#endif -#include -#include -#include - -#include -#define KNI_KTHREAD_MAX_RESCHEDULE_INTERVAL 1000000 /* us */ - -#define MBUF_BURST_SZ 32 - -/* Default carrier state for created KNI network interfaces */ -extern uint32_t kni_dflt_carrier; - -/* Request processing support for bifurcated drivers. */ -extern uint32_t bifurcated_support; - -/** - * A structure describing the private information for a kni device. - */ -struct kni_dev { - /* kni list */ - struct list_head list; - - uint8_t iova_mode; - - uint32_t core_id; /* Core ID to bind */ - char name[RTE_KNI_NAMESIZE]; /* Network device name */ - struct task_struct *pthread; - - /* wait queue for req/resp */ - wait_queue_head_t wq; - struct mutex sync_lock; - - /* kni device */ - struct net_device *net_dev; - - /* queue for packets to be sent out */ - struct rte_kni_fifo *tx_q; - - /* queue for the packets received */ - struct rte_kni_fifo *rx_q; - - /* queue for the allocated mbufs those can be used to save sk buffs */ - struct rte_kni_fifo *alloc_q; - - /* free queue for the mbufs to be freed */ - struct rte_kni_fifo *free_q; - - /* request queue */ - struct rte_kni_fifo *req_q; - - /* response queue */ - struct rte_kni_fifo *resp_q; - - void *sync_kva; - void *sync_va; - - void *mbuf_kva; - void *mbuf_va; - - /* mbuf size */ - uint32_t mbuf_size; - - /* buffers */ - void *pa[MBUF_BURST_SZ]; - void *va[MBUF_BURST_SZ]; - void *alloc_pa[MBUF_BURST_SZ]; - void *alloc_va[MBUF_BURST_SZ]; - - struct task_struct *usr_tsk; -}; - -#ifdef HAVE_IOVA_TO_KVA_MAPPING_SUPPORT -static inline phys_addr_t iova_to_phys(struct task_struct *tsk, - unsigned long iova) -{ - phys_addr_t offset, phys_addr; - struct page *page = NULL; - long ret; - - offset = iova & (PAGE_SIZE - 1); - - /* Read one page struct info */ -#ifdef HAVE_TSK_IN_GUP - ret = get_user_pages_remote(tsk, tsk->mm, iova, 1, 0, &page, NULL, NULL); -#else - #ifdef HAVE_VMA_IN_GUP - ret = get_user_pages_remote(tsk->mm, iova, 1, 0, &page, NULL, NULL); - #else - ret = get_user_pages_remote(tsk->mm, iova, 1, 0, &page, NULL); - #endif -#endif - if (ret < 0) - return 0; - - phys_addr = page_to_phys(page) | offset; - put_page(page); - - return phys_addr; -} - -static inline void *iova_to_kva(struct task_struct *tsk, unsigned long iova) -{ - return phys_to_virt(iova_to_phys(tsk, iova)); -} -#endif - -void kni_net_release_fifo_phy(struct kni_dev *kni); -void kni_net_rx(struct kni_dev *kni); -void kni_net_init(struct net_device *dev); -void kni_net_config_lo_mode(char *lo_str); -void kni_net_poll_resp(struct kni_dev *kni); - -#endif diff --git a/kernel/linux/kni/kni_fifo.h b/kernel/linux/kni/kni_fifo.h deleted file mode 100644 index 1ba5172002b6..000000000000 --- a/kernel/linux/kni/kni_fifo.h +++ /dev/null @@ -1,87 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright(c) 2010-2014 Intel Corporation. - */ - -#ifndef _KNI_FIFO_H_ -#define _KNI_FIFO_H_ - -#include - -/* Skip some memory barriers on Linux < 3.14 */ -#ifndef smp_load_acquire -#define smp_load_acquire(a) (*(a)) -#endif -#ifndef smp_store_release -#define smp_store_release(a, b) *(a) = (b) -#endif - -/** - * Adds num elements into the fifo. Return the number actually written - */ -static inline uint32_t -kni_fifo_put(struct rte_kni_fifo *fifo, void **data, uint32_t num) -{ - uint32_t i = 0; - uint32_t fifo_write = fifo->write; - uint32_t fifo_read = smp_load_acquire(&fifo->read); - uint32_t new_write = fifo_write; - - for (i = 0; i < num; i++) { - new_write = (new_write + 1) & (fifo->len - 1); - - if (new_write == fifo_read) - break; - fifo->buffer[fifo_write] = data[i]; - fifo_write = new_write; - } - smp_store_release(&fifo->write, fifo_write); - - return i; -} - -/** - * Get up to num elements from the FIFO. Return the number actually read - */ -static inline uint32_t -kni_fifo_get(struct rte_kni_fifo *fifo, void **data, uint32_t num) -{ - uint32_t i = 0; - uint32_t new_read = fifo->read; - uint32_t fifo_write = smp_load_acquire(&fifo->write); - - for (i = 0; i < num; i++) { - if (new_read == fifo_write) - break; - - data[i] = fifo->buffer[new_read]; - new_read = (new_read + 1) & (fifo->len - 1); - } - smp_store_release(&fifo->read, new_read); - - return i; -} - -/** - * Get the num of elements in the fifo - */ -static inline uint32_t -kni_fifo_count(struct rte_kni_fifo *fifo) -{ - uint32_t fifo_write = smp_load_acquire(&fifo->write); - uint32_t fifo_read = smp_load_acquire(&fifo->read); - return (fifo->len + fifo_write - fifo_read) & (fifo->len - 1); -} - -/** - * Get the num of available elements in the fifo - */ -static inline uint32_t -kni_fifo_free_count(struct rte_kni_fifo *fifo) -{ - uint32_t fifo_write = smp_load_acquire(&fifo->write); - uint32_t fifo_read = smp_load_acquire(&fifo->read); - return (fifo_read - fifo_write - 1) & (fifo->len - 1); -} - -#endif /* _KNI_FIFO_H_ */ diff --git a/kernel/linux/kni/kni_misc.c b/kernel/linux/kni/kni_misc.c deleted file mode 100644 index 0c3a86ee352e..000000000000 --- a/kernel/linux/kni/kni_misc.c +++ /dev/null @@ -1,719 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright(c) 2010-2014 Intel Corporation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "compat.h" -#include "kni_dev.h" - -MODULE_VERSION(KNI_VERSION); -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_AUTHOR("Intel Corporation"); -MODULE_DESCRIPTION("Kernel Module for managing kni devices"); - -#define KNI_RX_LOOP_NUM 1000 - -#define KNI_MAX_DEVICES 32 - -/* loopback mode */ -static char *lo_mode; - -/* Kernel thread mode */ -static char *kthread_mode; -static uint32_t multiple_kthread_on; - -/* Default carrier state for created KNI network interfaces */ -static char *carrier; -uint32_t kni_dflt_carrier; - -/* Request processing support for bifurcated drivers. */ -static char *enable_bifurcated; -uint32_t bifurcated_support; - -/* KNI thread scheduling interval */ -static long min_scheduling_interval = 100; /* us */ -static long max_scheduling_interval = 200; /* us */ - -#define KNI_DEV_IN_USE_BIT_NUM 0 /* Bit number for device in use */ - -static int kni_net_id; - -struct kni_net { - unsigned long device_in_use; /* device in use flag */ - struct mutex kni_kthread_lock; - struct task_struct *kni_kthread; - struct rw_semaphore kni_list_lock; - struct list_head kni_list_head; -}; - -static int __net_init -kni_init_net(struct net *net) -{ -#ifdef HAVE_SIMPLIFIED_PERNET_OPERATIONS - struct kni_net *knet = net_generic(net, kni_net_id); - - memset(knet, 0, sizeof(*knet)); -#else - struct kni_net *knet; - int ret; - - knet = kzalloc(sizeof(struct kni_net), GFP_KERNEL); - if (!knet) { - ret = -ENOMEM; - return ret; - } -#endif - - /* Clear the bit of device in use */ - clear_bit(KNI_DEV_IN_USE_BIT_NUM, &knet->device_in_use); - - mutex_init(&knet->kni_kthread_lock); - - init_rwsem(&knet->kni_list_lock); - INIT_LIST_HEAD(&knet->kni_list_head); - -#ifdef HAVE_SIMPLIFIED_PERNET_OPERATIONS - return 0; -#else - ret = net_assign_generic(net, kni_net_id, knet); - if (ret < 0) - kfree(knet); - - return ret; -#endif -} - -static void __net_exit -kni_exit_net(struct net *net) -{ - struct kni_net *knet __maybe_unused; - - knet = net_generic(net, kni_net_id); - mutex_destroy(&knet->kni_kthread_lock); - -#ifndef HAVE_SIMPLIFIED_PERNET_OPERATIONS - kfree(knet); -#endif -} - -static struct pernet_operations kni_net_ops = { - .init = kni_init_net, - .exit = kni_exit_net, -#ifdef HAVE_SIMPLIFIED_PERNET_OPERATIONS - .id = &kni_net_id, - .size = sizeof(struct kni_net), -#endif -}; - -static int -kni_thread_single(void *data) -{ - struct kni_net *knet = data; - int j; - struct kni_dev *dev; - - while (!kthread_should_stop()) { - down_read(&knet->kni_list_lock); - for (j = 0; j < KNI_RX_LOOP_NUM; j++) { - list_for_each_entry(dev, &knet->kni_list_head, list) { - kni_net_rx(dev); - kni_net_poll_resp(dev); - } - } - up_read(&knet->kni_list_lock); - /* reschedule out for a while */ - usleep_range(min_scheduling_interval, max_scheduling_interval); - } - - return 0; -} - -static int -kni_thread_multiple(void *param) -{ - int j; - struct kni_dev *dev = param; - - while (!kthread_should_stop()) { - for (j = 0; j < KNI_RX_LOOP_NUM; j++) { - kni_net_rx(dev); - kni_net_poll_resp(dev); - } - usleep_range(min_scheduling_interval, max_scheduling_interval); - } - - return 0; -} - -static int -kni_open(struct inode *inode, struct file *file) -{ - struct net *net = current->nsproxy->net_ns; - struct kni_net *knet = net_generic(net, kni_net_id); - - /* kni device can be opened by one user only per netns */ - if (test_and_set_bit(KNI_DEV_IN_USE_BIT_NUM, &knet->device_in_use)) - return -EBUSY; - - file->private_data = get_net(net); - pr_debug("/dev/kni opened\n"); - - return 0; -} - -static int -kni_dev_remove(struct kni_dev *dev) -{ - if (!dev) - return -ENODEV; - - /* - * The memory of kni device is allocated and released together - * with net device. Release mbuf before freeing net device. - */ - kni_net_release_fifo_phy(dev); - - if (dev->net_dev) { - unregister_netdev(dev->net_dev); - free_netdev(dev->net_dev); - } - - return 0; -} - -static int -kni_release(struct inode *inode, struct file *file) -{ - struct net *net = file->private_data; - struct kni_net *knet = net_generic(net, kni_net_id); - struct kni_dev *dev, *n; - - /* Stop kernel thread for single mode */ - if (multiple_kthread_on == 0) { - mutex_lock(&knet->kni_kthread_lock); - /* Stop kernel thread */ - if (knet->kni_kthread != NULL) { - kthread_stop(knet->kni_kthread); - knet->kni_kthread = NULL; - } - mutex_unlock(&knet->kni_kthread_lock); - } - - down_write(&knet->kni_list_lock); - list_for_each_entry_safe(dev, n, &knet->kni_list_head, list) { - /* Stop kernel thread for multiple mode */ - if (multiple_kthread_on && dev->pthread != NULL) { - kthread_stop(dev->pthread); - dev->pthread = NULL; - } - - list_del(&dev->list); - kni_dev_remove(dev); - } - up_write(&knet->kni_list_lock); - - /* Clear the bit of device in use */ - clear_bit(KNI_DEV_IN_USE_BIT_NUM, &knet->device_in_use); - - put_net(net); - pr_debug("/dev/kni closed\n"); - - return 0; -} - -static int -kni_check_param(struct kni_dev *kni, struct rte_kni_device_info *dev) -{ - if (!kni || !dev) - return -1; - - /* Check if network name has been used */ - if (!strncmp(kni->name, dev->name, RTE_KNI_NAMESIZE)) { - pr_err("KNI name %s duplicated\n", dev->name); - return -1; - } - - return 0; -} - -static int -kni_run_thread(struct kni_net *knet, struct kni_dev *kni, uint8_t force_bind) -{ - /** - * Create a new kernel thread for multiple mode, set its core affinity, - * and finally wake it up. - */ - if (multiple_kthread_on) { - kni->pthread = kthread_create(kni_thread_multiple, - (void *)kni, "kni_%s", kni->name); - if (IS_ERR(kni->pthread)) { - kni_dev_remove(kni); - return -ECANCELED; - } - - if (force_bind) - kthread_bind(kni->pthread, kni->core_id); - wake_up_process(kni->pthread); - } else { - mutex_lock(&knet->kni_kthread_lock); - - if (knet->kni_kthread == NULL) { - knet->kni_kthread = kthread_create(kni_thread_single, - (void *)knet, "kni_single"); - if (IS_ERR(knet->kni_kthread)) { - mutex_unlock(&knet->kni_kthread_lock); - kni_dev_remove(kni); - return -ECANCELED; - } - - if (force_bind) - kthread_bind(knet->kni_kthread, kni->core_id); - wake_up_process(knet->kni_kthread); - } - - mutex_unlock(&knet->kni_kthread_lock); - } - - return 0; -} - -static int -kni_ioctl_create(struct net *net, uint32_t ioctl_num, - unsigned long ioctl_param) -{ - struct kni_net *knet = net_generic(net, kni_net_id); - int ret; - struct rte_kni_device_info dev_info; - struct net_device *net_dev = NULL; - struct kni_dev *kni, *dev, *n; - - pr_info("Creating kni...\n"); - /* Check the buffer size, to avoid warning */ - if (_IOC_SIZE(ioctl_num) > sizeof(dev_info)) - return -EINVAL; - - /* Copy kni info from user space */ - if (copy_from_user(&dev_info, (void *)ioctl_param, sizeof(dev_info))) - return -EFAULT; - - /* Check if name is zero-ended */ - if (strnlen(dev_info.name, sizeof(dev_info.name)) == sizeof(dev_info.name)) { - pr_err("kni.name not zero-terminated"); - return -EINVAL; - } - - /** - * Check if the cpu core id is valid for binding. - */ - if (dev_info.force_bind && !cpu_online(dev_info.core_id)) { - pr_err("cpu %u is not online\n", dev_info.core_id); - return -EINVAL; - } - - /* Check if it has been created */ - down_read(&knet->kni_list_lock); - list_for_each_entry_safe(dev, n, &knet->kni_list_head, list) { - if (kni_check_param(dev, &dev_info) < 0) { - up_read(&knet->kni_list_lock); - return -EINVAL; - } - } - up_read(&knet->kni_list_lock); - - net_dev = alloc_netdev(sizeof(struct kni_dev), dev_info.name, -#ifdef NET_NAME_USER - NET_NAME_USER, -#endif - kni_net_init); - if (net_dev == NULL) { - pr_err("error allocating device \"%s\"\n", dev_info.name); - return -EBUSY; - } - - dev_net_set(net_dev, net); - - kni = netdev_priv(net_dev); - - kni->net_dev = net_dev; - kni->core_id = dev_info.core_id; - strncpy(kni->name, dev_info.name, RTE_KNI_NAMESIZE); - - /* Translate user space info into kernel space info */ - if (dev_info.iova_mode) { -#ifdef HAVE_IOVA_TO_KVA_MAPPING_SUPPORT - kni->tx_q = iova_to_kva(current, dev_info.tx_phys); - kni->rx_q = iova_to_kva(current, dev_info.rx_phys); - kni->alloc_q = iova_to_kva(current, dev_info.alloc_phys); - kni->free_q = iova_to_kva(current, dev_info.free_phys); - - kni->req_q = iova_to_kva(current, dev_info.req_phys); - kni->resp_q = iova_to_kva(current, dev_info.resp_phys); - kni->sync_va = dev_info.sync_va; - kni->sync_kva = iova_to_kva(current, dev_info.sync_phys); - kni->usr_tsk = current; - kni->iova_mode = 1; -#else - pr_err("KNI module does not support IOVA to VA translation\n"); - return -EINVAL; -#endif - } else { - - kni->tx_q = phys_to_virt(dev_info.tx_phys); - kni->rx_q = phys_to_virt(dev_info.rx_phys); - kni->alloc_q = phys_to_virt(dev_info.alloc_phys); - kni->free_q = phys_to_virt(dev_info.free_phys); - - kni->req_q = phys_to_virt(dev_info.req_phys); - kni->resp_q = phys_to_virt(dev_info.resp_phys); - kni->sync_va = dev_info.sync_va; - kni->sync_kva = phys_to_virt(dev_info.sync_phys); - kni->iova_mode = 0; - } - - kni->mbuf_size = dev_info.mbuf_size; - - pr_debug("tx_phys: 0x%016llx, tx_q addr: 0x%p\n", - (unsigned long long) dev_info.tx_phys, kni->tx_q); - pr_debug("rx_phys: 0x%016llx, rx_q addr: 0x%p\n", - (unsigned long long) dev_info.rx_phys, kni->rx_q); - pr_debug("alloc_phys: 0x%016llx, alloc_q addr: 0x%p\n", - (unsigned long long) dev_info.alloc_phys, kni->alloc_q); - pr_debug("free_phys: 0x%016llx, free_q addr: 0x%p\n", - (unsigned long long) dev_info.free_phys, kni->free_q); - pr_debug("req_phys: 0x%016llx, req_q addr: 0x%p\n", - (unsigned long long) dev_info.req_phys, kni->req_q); - pr_debug("resp_phys: 0x%016llx, resp_q addr: 0x%p\n", - (unsigned long long) dev_info.resp_phys, kni->resp_q); - pr_debug("mbuf_size: %u\n", kni->mbuf_size); - - /* if user has provided a valid mac address */ - if (is_valid_ether_addr(dev_info.mac_addr)) { -#ifdef HAVE_ETH_HW_ADDR_SET - eth_hw_addr_set(net_dev, dev_info.mac_addr); -#else - memcpy(net_dev->dev_addr, dev_info.mac_addr, ETH_ALEN); -#endif - } else { - /* Assign random MAC address. */ - eth_hw_addr_random(net_dev); - } - - if (dev_info.mtu) - net_dev->mtu = dev_info.mtu; -#ifdef HAVE_MAX_MTU_PARAM - net_dev->max_mtu = net_dev->mtu; - - if (dev_info.min_mtu) - net_dev->min_mtu = dev_info.min_mtu; - - if (dev_info.max_mtu) - net_dev->max_mtu = dev_info.max_mtu; -#endif - - ret = register_netdev(net_dev); - if (ret) { - pr_err("error %i registering device \"%s\"\n", - ret, dev_info.name); - kni->net_dev = NULL; - kni_dev_remove(kni); - free_netdev(net_dev); - return -ENODEV; - } - - netif_carrier_off(net_dev); - - ret = kni_run_thread(knet, kni, dev_info.force_bind); - if (ret != 0) - return ret; - - down_write(&knet->kni_list_lock); - list_add(&kni->list, &knet->kni_list_head); - up_write(&knet->kni_list_lock); - - return 0; -} - -static int -kni_ioctl_release(struct net *net, uint32_t ioctl_num, - unsigned long ioctl_param) -{ - struct kni_net *knet = net_generic(net, kni_net_id); - int ret = -EINVAL; - struct kni_dev *dev, *n; - struct rte_kni_device_info dev_info; - - if (_IOC_SIZE(ioctl_num) > sizeof(dev_info)) - return -EINVAL; - - if (copy_from_user(&dev_info, (void *)ioctl_param, sizeof(dev_info))) - return -EFAULT; - - /* Release the network device according to its name */ - if (strlen(dev_info.name) == 0) - return -EINVAL; - - down_write(&knet->kni_list_lock); - list_for_each_entry_safe(dev, n, &knet->kni_list_head, list) { - if (strncmp(dev->name, dev_info.name, RTE_KNI_NAMESIZE) != 0) - continue; - - if (multiple_kthread_on && dev->pthread != NULL) { - kthread_stop(dev->pthread); - dev->pthread = NULL; - } - - list_del(&dev->list); - kni_dev_remove(dev); - ret = 0; - break; - } - up_write(&knet->kni_list_lock); - pr_info("%s release kni named %s\n", - (ret == 0 ? "Successfully" : "Unsuccessfully"), dev_info.name); - - return ret; -} - -static long -kni_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param) -{ - long ret = -EINVAL; - struct net *net = current->nsproxy->net_ns; - - pr_debug("IOCTL num=0x%0x param=0x%0lx\n", ioctl_num, ioctl_param); - - /* - * Switch according to the ioctl called - */ - switch (_IOC_NR(ioctl_num)) { - case _IOC_NR(RTE_KNI_IOCTL_TEST): - /* For test only, not used */ - break; - case _IOC_NR(RTE_KNI_IOCTL_CREATE): - ret = kni_ioctl_create(net, ioctl_num, ioctl_param); - break; - case _IOC_NR(RTE_KNI_IOCTL_RELEASE): - ret = kni_ioctl_release(net, ioctl_num, ioctl_param); - break; - default: - pr_debug("IOCTL default\n"); - break; - } - - return ret; -} - -static long -kni_compat_ioctl(struct file *file, unsigned int ioctl_num, - unsigned long ioctl_param) -{ - /* 32 bits app on 64 bits OS to be supported later */ - pr_debug("Not implemented.\n"); - - return -EINVAL; -} - -static const struct file_operations kni_fops = { - .owner = THIS_MODULE, - .open = kni_open, - .release = kni_release, - .unlocked_ioctl = kni_ioctl, - .compat_ioctl = kni_compat_ioctl, -}; - -static struct miscdevice kni_misc = { - .minor = MISC_DYNAMIC_MINOR, - .name = KNI_DEVICE, - .fops = &kni_fops, -}; - -static int __init -kni_parse_kthread_mode(void) -{ - if (!kthread_mode) - return 0; - - if (strcmp(kthread_mode, "single") == 0) - return 0; - else if (strcmp(kthread_mode, "multiple") == 0) - multiple_kthread_on = 1; - else - return -1; - - return 0; -} - -static int __init -kni_parse_carrier_state(void) -{ - if (!carrier) { - kni_dflt_carrier = 0; - return 0; - } - - if (strcmp(carrier, "off") == 0) - kni_dflt_carrier = 0; - else if (strcmp(carrier, "on") == 0) - kni_dflt_carrier = 1; - else - return -1; - - return 0; -} - -static int __init -kni_parse_bifurcated_support(void) -{ - if (!enable_bifurcated) { - bifurcated_support = 0; - return 0; - } - - if (strcmp(enable_bifurcated, "on") == 0) - bifurcated_support = 1; - else - return -1; - - return 0; -} - -static int __init -kni_init(void) -{ - int rc; - - if (kni_parse_kthread_mode() < 0) { - pr_err("Invalid parameter for kthread_mode\n"); - return -EINVAL; - } - - if (multiple_kthread_on == 0) - pr_debug("Single kernel thread for all KNI devices\n"); - else - pr_debug("Multiple kernel thread mode enabled\n"); - - if (kni_parse_carrier_state() < 0) { - pr_err("Invalid parameter for carrier\n"); - return -EINVAL; - } - - if (kni_dflt_carrier == 0) - pr_debug("Default carrier state set to off.\n"); - else - pr_debug("Default carrier state set to on.\n"); - - if (kni_parse_bifurcated_support() < 0) { - pr_err("Invalid parameter for bifurcated support\n"); - return -EINVAL; - } - if (bifurcated_support == 1) - pr_debug("bifurcated support is enabled.\n"); - - if (min_scheduling_interval < 0 || max_scheduling_interval < 0 || - min_scheduling_interval > KNI_KTHREAD_MAX_RESCHEDULE_INTERVAL || - max_scheduling_interval > KNI_KTHREAD_MAX_RESCHEDULE_INTERVAL || - min_scheduling_interval >= max_scheduling_interval) { - pr_err("Invalid parameters for scheduling interval\n"); - return -EINVAL; - } - -#ifdef HAVE_SIMPLIFIED_PERNET_OPERATIONS - rc = register_pernet_subsys(&kni_net_ops); -#else - rc = register_pernet_gen_subsys(&kni_net_id, &kni_net_ops); -#endif - if (rc) - return -EPERM; - - rc = misc_register(&kni_misc); - if (rc != 0) { - pr_err("Misc registration failed\n"); - goto out; - } - - /* Configure the lo mode according to the input parameter */ - kni_net_config_lo_mode(lo_mode); - - return 0; - -out: -#ifdef HAVE_SIMPLIFIED_PERNET_OPERATIONS - unregister_pernet_subsys(&kni_net_ops); -#else - unregister_pernet_gen_subsys(kni_net_id, &kni_net_ops); -#endif - return rc; -} - -static void __exit -kni_exit(void) -{ - misc_deregister(&kni_misc); -#ifdef HAVE_SIMPLIFIED_PERNET_OPERATIONS - unregister_pernet_subsys(&kni_net_ops); -#else - unregister_pernet_gen_subsys(kni_net_id, &kni_net_ops); -#endif -} - -module_init(kni_init); -module_exit(kni_exit); - -module_param(lo_mode, charp, 0644); -MODULE_PARM_DESC(lo_mode, -"KNI loopback mode (default=lo_mode_none):\n" -"\t\tlo_mode_none Kernel loopback disabled\n" -"\t\tlo_mode_fifo Enable kernel loopback with fifo\n" -"\t\tlo_mode_fifo_skb Enable kernel loopback with fifo and skb buffer\n" -"\t\t" -); - -module_param(kthread_mode, charp, 0644); -MODULE_PARM_DESC(kthread_mode, -"Kernel thread mode (default=single):\n" -"\t\tsingle Single kernel thread mode enabled.\n" -"\t\tmultiple Multiple kernel thread mode enabled.\n" -"\t\t" -); - -module_param(carrier, charp, 0644); -MODULE_PARM_DESC(carrier, -"Default carrier state for KNI interface (default=off):\n" -"\t\toff Interfaces will be created with carrier state set to off.\n" -"\t\ton Interfaces will be created with carrier state set to on.\n" -"\t\t" -); - -module_param(enable_bifurcated, charp, 0644); -MODULE_PARM_DESC(enable_bifurcated, -"Enable request processing support for bifurcated drivers, " -"which means releasing rtnl_lock before calling userspace callback and " -"supporting async requests (default=off):\n" -"\t\ton Enable request processing support for bifurcated drivers.\n" -"\t\t" -); - -module_param(min_scheduling_interval, long, 0644); -MODULE_PARM_DESC(min_scheduling_interval, -"KNI thread min scheduling interval (default=100 microseconds)" -); - -module_param(max_scheduling_interval, long, 0644); -MODULE_PARM_DESC(max_scheduling_interval, -"KNI thread max scheduling interval (default=200 microseconds)" -); diff --git a/kernel/linux/kni/kni_net.c b/kernel/linux/kni/kni_net.c deleted file mode 100644 index 779ee3451a4c..000000000000 --- a/kernel/linux/kni/kni_net.c +++ /dev/null @@ -1,878 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright(c) 2010-2014 Intel Corporation. - */ - -/* - * This code is inspired from the book "Linux Device Drivers" by - * Alessandro Rubini and Jonathan Corbet, published by O'Reilly & Associates - */ - -#include -#include -#include -#include -#include /* eth_type_trans */ -#include -#include -#include -#include -#include - -#include -#include - -#include "compat.h" -#include "kni_dev.h" - -#define WD_TIMEOUT 5 /*jiffies */ - -#define KNI_WAIT_RESPONSE_TIMEOUT 300 /* 3 seconds */ - -/* typedef for rx function */ -typedef void (*kni_net_rx_t)(struct kni_dev *kni); - -static void kni_net_rx_normal(struct kni_dev *kni); - -/* kni rx function pointer, with default to normal rx */ -static kni_net_rx_t kni_net_rx_func = kni_net_rx_normal; - -#ifdef HAVE_IOVA_TO_KVA_MAPPING_SUPPORT -/* iova to kernel virtual address */ -static inline void * -iova2kva(struct kni_dev *kni, void *iova) -{ - return phys_to_virt(iova_to_phys(kni->usr_tsk, (unsigned long)iova)); -} - -static inline void * -iova2data_kva(struct kni_dev *kni, struct rte_kni_mbuf *m) -{ - return phys_to_virt(iova_to_phys(kni->usr_tsk, m->buf_iova) + - m->data_off); -} -#endif - -/* physical address to kernel virtual address */ -static void * -pa2kva(void *pa) -{ - return phys_to_virt((unsigned long)pa); -} - -/* physical address to virtual address */ -static void * -pa2va(void *pa, struct rte_kni_mbuf *m) -{ - void *va; - - va = (void *)((unsigned long)pa + - (unsigned long)m->buf_addr - - (unsigned long)m->buf_iova); - return va; -} - -/* mbuf data kernel virtual address from mbuf kernel virtual address */ -static void * -kva2data_kva(struct rte_kni_mbuf *m) -{ - return phys_to_virt(m->buf_iova + m->data_off); -} - -static inline void * -get_kva(struct kni_dev *kni, void *pa) -{ -#ifdef HAVE_IOVA_TO_KVA_MAPPING_SUPPORT - if (kni->iova_mode == 1) - return iova2kva(kni, pa); -#endif - return pa2kva(pa); -} - -static inline void * -get_data_kva(struct kni_dev *kni, void *pkt_kva) -{ -#ifdef HAVE_IOVA_TO_KVA_MAPPING_SUPPORT - if (kni->iova_mode == 1) - return iova2data_kva(kni, pkt_kva); -#endif - return kva2data_kva(pkt_kva); -} - -/* - * It can be called to process the request. - */ -static int -kni_net_process_request(struct net_device *dev, struct rte_kni_request *req) -{ - struct kni_dev *kni = netdev_priv(dev); - int ret = -1; - void *resp_va; - uint32_t num; - int ret_val; - - ASSERT_RTNL(); - - if (bifurcated_support) { - /* If we need to wait and RTNL mutex is held - * drop the mutex and hold reference to keep device - */ - if (req->async == 0) { - dev_hold(dev); - rtnl_unlock(); - } - } - - mutex_lock(&kni->sync_lock); - - /* Construct data */ - memcpy(kni->sync_kva, req, sizeof(struct rte_kni_request)); - num = kni_fifo_put(kni->req_q, &kni->sync_va, 1); - if (num < 1) { - pr_err("Cannot send to req_q\n"); - ret = -EBUSY; - goto fail; - } - - if (bifurcated_support) { - /* No result available since request is handled - * asynchronously. set response to success. - */ - if (req->async != 0) { - req->result = 0; - goto async; - } - } - - ret_val = wait_event_interruptible_timeout(kni->wq, - kni_fifo_count(kni->resp_q), 3 * HZ); - if (signal_pending(current) || ret_val <= 0) { - ret = -ETIME; - goto fail; - } - num = kni_fifo_get(kni->resp_q, (void **)&resp_va, 1); - if (num != 1 || resp_va != kni->sync_va) { - /* This should never happen */ - pr_err("No data in resp_q\n"); - ret = -ENODATA; - goto fail; - } - - memcpy(req, kni->sync_kva, sizeof(struct rte_kni_request)); -async: - ret = 0; - -fail: - mutex_unlock(&kni->sync_lock); - if (bifurcated_support) { - if (req->async == 0) { - rtnl_lock(); - dev_put(dev); - } - } - return ret; -} - -/* - * Open and close - */ -static int -kni_net_open(struct net_device *dev) -{ - int ret; - struct rte_kni_request req; - - netif_start_queue(dev); - if (kni_dflt_carrier == 1) - netif_carrier_on(dev); - else - netif_carrier_off(dev); - - memset(&req, 0, sizeof(req)); - req.req_id = RTE_KNI_REQ_CFG_NETWORK_IF; - - /* Setting if_up to non-zero means up */ - req.if_up = 1; - ret = kni_net_process_request(dev, &req); - - return (ret == 0) ? req.result : ret; -} - -static int -kni_net_release(struct net_device *dev) -{ - int ret; - struct rte_kni_request req; - - netif_stop_queue(dev); /* can't transmit any more */ - netif_carrier_off(dev); - - memset(&req, 0, sizeof(req)); - req.req_id = RTE_KNI_REQ_CFG_NETWORK_IF; - - /* Setting if_up to 0 means down */ - req.if_up = 0; - - if (bifurcated_support) { - /* request async because of the deadlock problem */ - req.async = 1; - } - - ret = kni_net_process_request(dev, &req); - - return (ret == 0) ? req.result : ret; -} - -static void -kni_fifo_trans_pa2va(struct kni_dev *kni, - struct rte_kni_fifo *src_pa, struct rte_kni_fifo *dst_va) -{ - uint32_t ret, i, num_dst, num_rx; - struct rte_kni_mbuf *kva, *prev_kva; - int nb_segs; - int kva_nb_segs; - - do { - num_dst = kni_fifo_free_count(dst_va); - if (num_dst == 0) - return; - - num_rx = min_t(uint32_t, num_dst, MBUF_BURST_SZ); - - num_rx = kni_fifo_get(src_pa, kni->pa, num_rx); - if (num_rx == 0) - return; - - for (i = 0; i < num_rx; i++) { - kva = get_kva(kni, kni->pa[i]); - kni->va[i] = pa2va(kni->pa[i], kva); - - kva_nb_segs = kva->nb_segs; - for (nb_segs = 0; nb_segs < kva_nb_segs; nb_segs++) { - if (!kva->next) - break; - - prev_kva = kva; - kva = get_kva(kni, kva->next); - /* Convert physical address to virtual address */ - prev_kva->next = pa2va(prev_kva->next, kva); - } - } - - ret = kni_fifo_put(dst_va, kni->va, num_rx); - if (ret != num_rx) { - /* Failing should not happen */ - pr_err("Fail to enqueue entries into dst_va\n"); - return; - } - } while (1); -} - -/* Try to release mbufs when kni release */ -void kni_net_release_fifo_phy(struct kni_dev *kni) -{ - /* release rx_q first, because it can't release in userspace */ - kni_fifo_trans_pa2va(kni, kni->rx_q, kni->free_q); - /* release alloc_q for speeding up kni release in userspace */ - kni_fifo_trans_pa2va(kni, kni->alloc_q, kni->free_q); -} - -/* - * Configuration changes (passed on by ifconfig) - */ -static int -kni_net_config(struct net_device *dev, struct ifmap *map) -{ - if (dev->flags & IFF_UP) /* can't act on a running interface */ - return -EBUSY; - - /* ignore other fields */ - return 0; -} - -/* - * Transmit a packet (called by the kernel) - */ -static int -kni_net_tx(struct sk_buff *skb, struct net_device *dev) -{ - int len = 0; - uint32_t ret; - struct kni_dev *kni = netdev_priv(dev); - struct rte_kni_mbuf *pkt_kva = NULL; - void *pkt_pa = NULL; - void *pkt_va = NULL; - - /* save the timestamp */ -#ifdef HAVE_TRANS_START_HELPER - netif_trans_update(dev); -#else - dev->trans_start = jiffies; -#endif - - /* Check if the length of skb is less than mbuf size */ - if (skb->len > kni->mbuf_size) - goto drop; - - /** - * Check if it has at least one free entry in tx_q and - * one entry in alloc_q. - */ - if (kni_fifo_free_count(kni->tx_q) == 0 || - kni_fifo_count(kni->alloc_q) == 0) { - /** - * If no free entry in tx_q or no entry in alloc_q, - * drops skb and goes out. - */ - goto drop; - } - - /* dequeue a mbuf from alloc_q */ - ret = kni_fifo_get(kni->alloc_q, &pkt_pa, 1); - if (likely(ret == 1)) { - void *data_kva; - - pkt_kva = get_kva(kni, pkt_pa); - data_kva = get_data_kva(kni, pkt_kva); - pkt_va = pa2va(pkt_pa, pkt_kva); - - len = skb->len; - memcpy(data_kva, skb->data, len); - if (unlikely(len < ETH_ZLEN)) { - memset(data_kva + len, 0, ETH_ZLEN - len); - len = ETH_ZLEN; - } - pkt_kva->pkt_len = len; - pkt_kva->data_len = len; - - /* enqueue mbuf into tx_q */ - ret = kni_fifo_put(kni->tx_q, &pkt_va, 1); - if (unlikely(ret != 1)) { - /* Failing should not happen */ - pr_err("Fail to enqueue mbuf into tx_q\n"); - goto drop; - } - } else { - /* Failing should not happen */ - pr_err("Fail to dequeue mbuf from alloc_q\n"); - goto drop; - } - - /* Free skb and update statistics */ - dev_kfree_skb(skb); - dev->stats.tx_bytes += len; - dev->stats.tx_packets++; - - return NETDEV_TX_OK; - -drop: - /* Free skb and update statistics */ - dev_kfree_skb(skb); - dev->stats.tx_dropped++; - - return NETDEV_TX_OK; -} - -/* - * RX: normal working mode - */ -static void -kni_net_rx_normal(struct kni_dev *kni) -{ - uint32_t ret; - uint32_t len; - uint32_t i, num_rx, num_fq; - struct rte_kni_mbuf *kva, *prev_kva; - void *data_kva; - struct sk_buff *skb; - struct net_device *dev = kni->net_dev; - - /* Get the number of free entries in free_q */ - num_fq = kni_fifo_free_count(kni->free_q); - if (num_fq == 0) { - /* No room on the free_q, bail out */ - return; - } - - /* Calculate the number of entries to dequeue from rx_q */ - num_rx = min_t(uint32_t, num_fq, MBUF_BURST_SZ); - - /* Burst dequeue from rx_q */ - num_rx = kni_fifo_get(kni->rx_q, kni->pa, num_rx); - if (num_rx == 0) - return; - - /* Transfer received packets to netif */ - for (i = 0; i < num_rx; i++) { - kva = get_kva(kni, kni->pa[i]); - len = kva->pkt_len; - data_kva = get_data_kva(kni, kva); - kni->va[i] = pa2va(kni->pa[i], kva); - - skb = netdev_alloc_skb(dev, len); - if (!skb) { - /* Update statistics */ - dev->stats.rx_dropped++; - continue; - } - - if (kva->nb_segs == 1) { - memcpy(skb_put(skb, len), data_kva, len); - } else { - int nb_segs; - int kva_nb_segs = kva->nb_segs; - - for (nb_segs = 0; nb_segs < kva_nb_segs; nb_segs++) { - memcpy(skb_put(skb, kva->data_len), - data_kva, kva->data_len); - - if (!kva->next) - break; - - prev_kva = kva; - kva = get_kva(kni, kva->next); - data_kva = kva2data_kva(kva); - /* Convert physical address to virtual address */ - prev_kva->next = pa2va(prev_kva->next, kva); - } - } - - skb->protocol = eth_type_trans(skb, dev); - skb->ip_summed = CHECKSUM_UNNECESSARY; - - /* Call netif interface */ -#ifdef HAVE_NETIF_RX_NI - netif_rx_ni(skb); -#else - netif_rx(skb); -#endif - - /* Update statistics */ - dev->stats.rx_bytes += len; - dev->stats.rx_packets++; - } - - /* Burst enqueue mbufs into free_q */ - ret = kni_fifo_put(kni->free_q, kni->va, num_rx); - if (ret != num_rx) - /* Failing should not happen */ - pr_err("Fail to enqueue entries into free_q\n"); -} - -/* - * RX: loopback with enqueue/dequeue fifos. - */ -static void -kni_net_rx_lo_fifo(struct kni_dev *kni) -{ - uint32_t ret; - uint32_t len; - uint32_t i, num, num_rq, num_tq, num_aq, num_fq; - struct rte_kni_mbuf *kva, *next_kva; - void *data_kva; - struct rte_kni_mbuf *alloc_kva; - void *alloc_data_kva; - struct net_device *dev = kni->net_dev; - - /* Get the number of entries in rx_q */ - num_rq = kni_fifo_count(kni->rx_q); - - /* Get the number of free entries in tx_q */ - num_tq = kni_fifo_free_count(kni->tx_q); - - /* Get the number of entries in alloc_q */ - num_aq = kni_fifo_count(kni->alloc_q); - - /* Get the number of free entries in free_q */ - num_fq = kni_fifo_free_count(kni->free_q); - - /* Calculate the number of entries to be dequeued from rx_q */ - num = min(num_rq, num_tq); - num = min(num, num_aq); - num = min(num, num_fq); - num = min_t(uint32_t, num, MBUF_BURST_SZ); - - /* Return if no entry to dequeue from rx_q */ - if (num == 0) - return; - - /* Burst dequeue from rx_q */ - ret = kni_fifo_get(kni->rx_q, kni->pa, num); - if (ret == 0) - return; /* Failing should not happen */ - - /* Dequeue entries from alloc_q */ - ret = kni_fifo_get(kni->alloc_q, kni->alloc_pa, num); - if (ret) { - num = ret; - /* Copy mbufs */ - for (i = 0; i < num; i++) { - kva = get_kva(kni, kni->pa[i]); - len = kva->data_len; - data_kva = get_data_kva(kni, kva); - kni->va[i] = pa2va(kni->pa[i], kva); - - while (kva->next) { - next_kva = get_kva(kni, kva->next); - /* Convert physical address to virtual address */ - kva->next = pa2va(kva->next, next_kva); - kva = next_kva; - } - - alloc_kva = get_kva(kni, kni->alloc_pa[i]); - alloc_data_kva = get_data_kva(kni, alloc_kva); - kni->alloc_va[i] = pa2va(kni->alloc_pa[i], alloc_kva); - - memcpy(alloc_data_kva, data_kva, len); - alloc_kva->pkt_len = len; - alloc_kva->data_len = len; - - dev->stats.tx_bytes += len; - dev->stats.rx_bytes += len; - } - - /* Burst enqueue mbufs into tx_q */ - ret = kni_fifo_put(kni->tx_q, kni->alloc_va, num); - if (ret != num) - /* Failing should not happen */ - pr_err("Fail to enqueue mbufs into tx_q\n"); - } - - /* Burst enqueue mbufs into free_q */ - ret = kni_fifo_put(kni->free_q, kni->va, num); - if (ret != num) - /* Failing should not happen */ - pr_err("Fail to enqueue mbufs into free_q\n"); - - /** - * Update statistic, and enqueue/dequeue failure is impossible, - * as all queues are checked at first. - */ - dev->stats.tx_packets += num; - dev->stats.rx_packets += num; -} - -/* - * RX: loopback with enqueue/dequeue fifos and sk buffer copies. - */ -static void -kni_net_rx_lo_fifo_skb(struct kni_dev *kni) -{ - uint32_t ret; - uint32_t len; - uint32_t i, num_rq, num_fq, num; - struct rte_kni_mbuf *kva, *prev_kva; - void *data_kva; - struct sk_buff *skb; - struct net_device *dev = kni->net_dev; - - /* Get the number of entries in rx_q */ - num_rq = kni_fifo_count(kni->rx_q); - - /* Get the number of free entries in free_q */ - num_fq = kni_fifo_free_count(kni->free_q); - - /* Calculate the number of entries to dequeue from rx_q */ - num = min(num_rq, num_fq); - num = min_t(uint32_t, num, MBUF_BURST_SZ); - - /* Return if no entry to dequeue from rx_q */ - if (num == 0) - return; - - /* Burst dequeue mbufs from rx_q */ - ret = kni_fifo_get(kni->rx_q, kni->pa, num); - if (ret == 0) - return; - - /* Copy mbufs to sk buffer and then call tx interface */ - for (i = 0; i < num; i++) { - kva = get_kva(kni, kni->pa[i]); - len = kva->pkt_len; - data_kva = get_data_kva(kni, kva); - kni->va[i] = pa2va(kni->pa[i], kva); - - skb = netdev_alloc_skb(dev, len); - if (skb) { - memcpy(skb_put(skb, len), data_kva, len); - skb->ip_summed = CHECKSUM_UNNECESSARY; - dev_kfree_skb(skb); - } - - /* Simulate real usage, allocate/copy skb twice */ - skb = netdev_alloc_skb(dev, len); - if (skb == NULL) { - dev->stats.rx_dropped++; - continue; - } - - if (kva->nb_segs == 1) { - memcpy(skb_put(skb, len), data_kva, len); - } else { - int nb_segs; - int kva_nb_segs = kva->nb_segs; - - for (nb_segs = 0; nb_segs < kva_nb_segs; nb_segs++) { - memcpy(skb_put(skb, kva->data_len), - data_kva, kva->data_len); - - if (!kva->next) - break; - - prev_kva = kva; - kva = get_kva(kni, kva->next); - data_kva = get_data_kva(kni, kva); - /* Convert physical address to virtual address */ - prev_kva->next = pa2va(prev_kva->next, kva); - } - } - - skb->ip_summed = CHECKSUM_UNNECESSARY; - - dev->stats.rx_bytes += len; - dev->stats.rx_packets++; - - /* call tx interface */ - kni_net_tx(skb, dev); - } - - /* enqueue all the mbufs from rx_q into free_q */ - ret = kni_fifo_put(kni->free_q, kni->va, num); - if (ret != num) - /* Failing should not happen */ - pr_err("Fail to enqueue mbufs into free_q\n"); -} - -/* rx interface */ -void -kni_net_rx(struct kni_dev *kni) -{ - /** - * It doesn't need to check if it is NULL pointer, - * as it has a default value - */ - (*kni_net_rx_func)(kni); -} - -/* - * Deal with a transmit timeout. - */ -#ifdef HAVE_TX_TIMEOUT_TXQUEUE -static void -kni_net_tx_timeout(struct net_device *dev, unsigned int txqueue) -#else -static void -kni_net_tx_timeout(struct net_device *dev) -#endif -{ - pr_debug("Transmit timeout at %ld, latency %ld\n", jiffies, - jiffies - dev_trans_start(dev)); - - dev->stats.tx_errors++; - netif_wake_queue(dev); -} - -static int -kni_net_change_mtu(struct net_device *dev, int new_mtu) -{ - int ret; - struct rte_kni_request req; - - pr_debug("kni_net_change_mtu new mtu %d to be set\n", new_mtu); - - memset(&req, 0, sizeof(req)); - req.req_id = RTE_KNI_REQ_CHANGE_MTU; - req.new_mtu = new_mtu; - ret = kni_net_process_request(dev, &req); - if (ret == 0 && req.result == 0) - dev->mtu = new_mtu; - - return (ret == 0) ? req.result : ret; -} - -static void -kni_net_change_rx_flags(struct net_device *netdev, int flags) -{ - struct rte_kni_request req; - - memset(&req, 0, sizeof(req)); - - if (flags & IFF_ALLMULTI) { - req.req_id = RTE_KNI_REQ_CHANGE_ALLMULTI; - - if (netdev->flags & IFF_ALLMULTI) - req.allmulti = 1; - else - req.allmulti = 0; - } - - if (flags & IFF_PROMISC) { - req.req_id = RTE_KNI_REQ_CHANGE_PROMISC; - - if (netdev->flags & IFF_PROMISC) - req.promiscusity = 1; - else - req.promiscusity = 0; - } - - kni_net_process_request(netdev, &req); -} - -/* - * Checks if the user space application provided the resp message - */ -void -kni_net_poll_resp(struct kni_dev *kni) -{ - if (kni_fifo_count(kni->resp_q)) - wake_up_interruptible(&kni->wq); -} - -/* - * Fill the eth header - */ -static int -kni_net_header(struct sk_buff *skb, struct net_device *dev, - unsigned short type, const void *daddr, - const void *saddr, uint32_t len) -{ - struct ethhdr *eth = (struct ethhdr *) skb_push(skb, ETH_HLEN); - - memcpy(eth->h_source, saddr ? saddr : dev->dev_addr, dev->addr_len); - memcpy(eth->h_dest, daddr ? daddr : dev->dev_addr, dev->addr_len); - eth->h_proto = htons(type); - - return dev->hard_header_len; -} - -/* - * Re-fill the eth header - */ -#ifdef HAVE_REBUILD_HEADER -static int -kni_net_rebuild_header(struct sk_buff *skb) -{ - struct net_device *dev = skb->dev; - struct ethhdr *eth = (struct ethhdr *) skb->data; - - memcpy(eth->h_source, dev->dev_addr, dev->addr_len); - memcpy(eth->h_dest, dev->dev_addr, dev->addr_len); - - return 0; -} -#endif /* < 4.1.0 */ - -/** - * kni_net_set_mac - Change the Ethernet Address of the KNI NIC - * @netdev: network interface device structure - * @p: pointer to an address structure - * - * Returns 0 on success, negative on failure - **/ -static int -kni_net_set_mac(struct net_device *netdev, void *p) -{ - int ret; - struct rte_kni_request req; - struct sockaddr *addr = p; - - memset(&req, 0, sizeof(req)); - req.req_id = RTE_KNI_REQ_CHANGE_MAC_ADDR; - - if (!is_valid_ether_addr((unsigned char *)(addr->sa_data))) - return -EADDRNOTAVAIL; - - memcpy(req.mac_addr, addr->sa_data, netdev->addr_len); -#ifdef HAVE_ETH_HW_ADDR_SET - eth_hw_addr_set(netdev, addr->sa_data); -#else - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); -#endif - - ret = kni_net_process_request(netdev, &req); - - return (ret == 0 ? req.result : ret); -} - -#ifdef HAVE_CHANGE_CARRIER_CB -static int -kni_net_change_carrier(struct net_device *dev, bool new_carrier) -{ - if (new_carrier) - netif_carrier_on(dev); - else - netif_carrier_off(dev); - return 0; -} -#endif - -static const struct header_ops kni_net_header_ops = { - .create = kni_net_header, - .parse = eth_header_parse, -#ifdef HAVE_REBUILD_HEADER - .rebuild = kni_net_rebuild_header, -#endif /* < 4.1.0 */ - .cache = NULL, /* disable caching */ -}; - -static const struct net_device_ops kni_net_netdev_ops = { - .ndo_open = kni_net_open, - .ndo_stop = kni_net_release, - .ndo_set_config = kni_net_config, - .ndo_change_rx_flags = kni_net_change_rx_flags, - .ndo_start_xmit = kni_net_tx, - .ndo_change_mtu = kni_net_change_mtu, - .ndo_tx_timeout = kni_net_tx_timeout, - .ndo_set_mac_address = kni_net_set_mac, -#ifdef HAVE_CHANGE_CARRIER_CB - .ndo_change_carrier = kni_net_change_carrier, -#endif -}; - -static void kni_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - strlcpy(info->version, KNI_VERSION, sizeof(info->version)); - strlcpy(info->driver, "kni", sizeof(info->driver)); -} - -static const struct ethtool_ops kni_net_ethtool_ops = { - .get_drvinfo = kni_get_drvinfo, - .get_link = ethtool_op_get_link, -}; - -void -kni_net_init(struct net_device *dev) -{ - struct kni_dev *kni = netdev_priv(dev); - - init_waitqueue_head(&kni->wq); - mutex_init(&kni->sync_lock); - - ether_setup(dev); /* assign some of the fields */ - dev->netdev_ops = &kni_net_netdev_ops; - dev->header_ops = &kni_net_header_ops; - dev->ethtool_ops = &kni_net_ethtool_ops; - dev->watchdog_timeo = WD_TIMEOUT; -} - -void -kni_net_config_lo_mode(char *lo_str) -{ - if (!lo_str) { - pr_debug("loopback disabled"); - return; - } - - if (!strcmp(lo_str, "lo_mode_none")) - pr_debug("loopback disabled"); - else if (!strcmp(lo_str, "lo_mode_fifo")) { - pr_debug("loopback mode=lo_mode_fifo enabled"); - kni_net_rx_func = kni_net_rx_lo_fifo; - } else if (!strcmp(lo_str, "lo_mode_fifo_skb")) { - pr_debug("loopback mode=lo_mode_fifo_skb enabled"); - kni_net_rx_func = kni_net_rx_lo_fifo_skb; - } else { - pr_debug("Unknown loopback parameter, disabled"); - } -} diff --git a/kernel/linux/kni/meson.build b/kernel/linux/kni/meson.build deleted file mode 100644 index 4c90069e9989..000000000000 --- a/kernel/linux/kni/meson.build +++ /dev/null @@ -1,41 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2018 Luca Boccassi - -# For SUSE build check function arguments of ndo_tx_timeout API -# Ref: https://jira.devtools.intel.com/browse/DPDK-29263 -kmod_cflags = '' -file_path = kernel_source_dir + '/include/linux/netdevice.h' -run_cmd = run_command('grep', 'ndo_tx_timeout', file_path, check: false) - -if run_cmd.stdout().contains('txqueue') == true - kmod_cflags = '-DHAVE_ARG_TX_QUEUE' -endif - - -kni_mkfile = custom_target('rte_kni_makefile', - output: 'Makefile', - command: ['touch', '@OUTPUT@']) - -kni_sources = files( - 'kni_misc.c', - 'kni_net.c', - 'Kbuild', -) - -custom_target('rte_kni', - input: kni_sources, - output: 'rte_kni.ko', - command: ['make', '-j4', '-C', kernel_build_dir, - 'M=' + meson.current_build_dir(), - 'src=' + meson.current_source_dir(), - ' '.join(['MODULE_CFLAGS=', kmod_cflags,'-include ']) - + dpdk_source_root + '/config/rte_config.h' + - ' -I' + dpdk_source_root + '/lib/eal/include' + - ' -I' + dpdk_source_root + '/lib/kni' + - ' -I' + dpdk_build_root + - ' -I' + meson.current_source_dir(), - 'modules'] + cross_args, - depends: kni_mkfile, - install: install, - install_dir: kernel_install_dir, - build_by_default: get_option('enable_kmods')) diff --git a/kernel/linux/meson.build b/kernel/linux/meson.build index 16a094899446..8d47074621f7 100644 --- a/kernel/linux/meson.build +++ b/kernel/linux/meson.build @@ -1,7 +1,7 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2018 Intel Corporation -subdirs = ['kni'] +subdirs = [] kernel_build_dir = get_option('kernel_dir') kernel_source_dir = get_option('kernel_dir') diff --git a/lib/eal/common/eal_common_log.c b/lib/eal/common/eal_common_log.c index bd7b188ceb4a..0a1d219d6924 100644 --- a/lib/eal/common/eal_common_log.c +++ b/lib/eal/common/eal_common_log.c @@ -356,7 +356,6 @@ static const struct logtype logtype_strings[] = { {RTE_LOGTYPE_PMD, "pmd"}, {RTE_LOGTYPE_HASH, "lib.hash"}, {RTE_LOGTYPE_LPM, "lib.lpm"}, - {RTE_LOGTYPE_KNI, "lib.kni"}, {RTE_LOGTYPE_ACL, "lib.acl"}, {RTE_LOGTYPE_POWER, "lib.power"}, {RTE_LOGTYPE_METER, "lib.meter"}, diff --git a/lib/eal/include/rte_log.h b/lib/eal/include/rte_log.h index 6d2b0856a565..bdefff2a5933 100644 --- a/lib/eal/include/rte_log.h +++ b/lib/eal/include/rte_log.h @@ -34,7 +34,7 @@ extern "C" { #define RTE_LOGTYPE_PMD 5 /**< Log related to poll mode driver. */ #define RTE_LOGTYPE_HASH 6 /**< Log related to hash table. */ #define RTE_LOGTYPE_LPM 7 /**< Log related to LPM. */ -#define RTE_LOGTYPE_KNI 8 /**< Log related to KNI. */ + /* was RTE_LOGTYPE_KNI */ #define RTE_LOGTYPE_ACL 9 /**< Log related to ACL. */ #define RTE_LOGTYPE_POWER 10 /**< Log related to power. */ #define RTE_LOGTYPE_METER 11 /**< Log related to QoS meter. */ diff --git a/lib/eal/linux/eal.c b/lib/eal/linux/eal.c index c6efd920145c..a1fefcd9d83a 100644 --- a/lib/eal/linux/eal.c +++ b/lib/eal/linux/eal.c @@ -1084,11 +1084,6 @@ 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_LIB_KNI) && LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 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 performance.\n"); -#endif } else if (is_iommu_enabled()) { /* we have an IOMMU, pick IOVA as VA mode */ iova_mode = RTE_IOVA_VA; @@ -1101,20 +1096,6 @@ rte_eal_init(int argc, char **argv) RTE_LOG(DEBUG, EAL, "IOMMU is not available, selecting IOVA as PA mode.\n"); } } -#if defined(RTE_LIB_KNI) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) - /* Workaround for KNI which requires physical address to work - * in kernels < 4.10 - */ - if (iova_mode == RTE_IOVA_VA && - rte_eal_check_module("rte_kni") == 1) { - if (phys_addrs) { - iova_mode = RTE_IOVA_PA; - RTE_LOG(WARNING, EAL, "Forcing IOVA as 'PA' because KNI module is loaded\n"); - } else { - RTE_LOG(DEBUG, EAL, "KNI can not work since physical addresses are unavailable\n"); - } - } -#endif rte_eal_get_configuration()->iova_mode = iova_mode; } else { rte_eal_get_configuration()->iova_mode = diff --git a/lib/kni/meson.build b/lib/kni/meson.build deleted file mode 100644 index 5ce410f7f2d2..000000000000 --- a/lib/kni/meson.build +++ /dev/null @@ -1,21 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2017 Intel Corporation - -if is_windows - build = false - reason = 'not supported on Windows' - subdir_done() -endif - -if dpdk_conf.get('RTE_IOVA_IN_MBUF') == 0 - build = false - reason = 'requires IOVA in mbuf (set enable_iova_as_pa option)' -endif - -if not is_linux or not dpdk_conf.get('RTE_ARCH_64') - build = false - reason = 'only supported on 64-bit Linux' -endif -sources = files('rte_kni.c') -headers = files('rte_kni.h', 'rte_kni_common.h') -deps += ['ethdev', 'pci'] diff --git a/lib/kni/rte_kni.c b/lib/kni/rte_kni.c deleted file mode 100644 index bfa6a001ff59..000000000000 --- a/lib/kni/rte_kni.c +++ /dev/null @@ -1,843 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation - */ - -#ifndef RTE_EXEC_ENV_LINUX -#error "KNI is not supported" -#endif - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "rte_kni_fifo.h" - -#define MAX_MBUF_BURST_NUM 32 - -/* Maximum number of ring entries */ -#define KNI_FIFO_COUNT_MAX 1024 -#define KNI_FIFO_SIZE (KNI_FIFO_COUNT_MAX * sizeof(void *) + \ - sizeof(struct rte_kni_fifo)) - -#define KNI_REQUEST_MBUF_NUM_MAX 32 - -#define KNI_MEM_CHECK(cond, fail) do { if (cond) goto fail; } while (0) - -#define KNI_MZ_NAME_FMT "kni_info_%s" -#define KNI_TX_Q_MZ_NAME_FMT "kni_tx_%s" -#define KNI_RX_Q_MZ_NAME_FMT "kni_rx_%s" -#define KNI_ALLOC_Q_MZ_NAME_FMT "kni_alloc_%s" -#define KNI_FREE_Q_MZ_NAME_FMT "kni_free_%s" -#define KNI_REQ_Q_MZ_NAME_FMT "kni_req_%s" -#define KNI_RESP_Q_MZ_NAME_FMT "kni_resp_%s" -#define KNI_SYNC_ADDR_MZ_NAME_FMT "kni_sync_%s" - -TAILQ_HEAD(rte_kni_list, rte_tailq_entry); - -static struct rte_tailq_elem rte_kni_tailq = { - .name = "RTE_KNI", -}; -EAL_REGISTER_TAILQ(rte_kni_tailq) - -/** - * KNI context - */ -struct rte_kni { - char name[RTE_KNI_NAMESIZE]; /**< KNI interface name */ - uint16_t group_id; /**< Group ID of KNI devices */ - uint32_t slot_id; /**< KNI pool slot ID */ - struct rte_mempool *pktmbuf_pool; /**< pkt mbuf mempool */ - unsigned int mbuf_size; /**< mbuf size */ - - const struct rte_memzone *m_tx_q; /**< TX queue memzone */ - const struct rte_memzone *m_rx_q; /**< RX queue memzone */ - const struct rte_memzone *m_alloc_q;/**< Alloc queue memzone */ - const struct rte_memzone *m_free_q; /**< Free queue memzone */ - - struct rte_kni_fifo *tx_q; /**< TX queue */ - struct rte_kni_fifo *rx_q; /**< RX queue */ - struct rte_kni_fifo *alloc_q; /**< Allocated mbufs queue */ - struct rte_kni_fifo *free_q; /**< To be freed mbufs queue */ - - const struct rte_memzone *m_req_q; /**< Request queue memzone */ - const struct rte_memzone *m_resp_q; /**< Response queue memzone */ - const struct rte_memzone *m_sync_addr;/**< Sync addr memzone */ - - /* For request & response */ - struct rte_kni_fifo *req_q; /**< Request queue */ - struct rte_kni_fifo *resp_q; /**< Response queue */ - void *sync_addr; /**< Req/Resp Mem address */ - - struct rte_kni_ops ops; /**< operations for request */ -}; - -enum kni_ops_status { - KNI_REQ_NO_REGISTER = 0, - KNI_REQ_REGISTERED, -}; - -static void kni_free_mbufs(struct rte_kni *kni); -static void kni_allocate_mbufs(struct rte_kni *kni); - -static volatile int kni_fd = -1; - -/* Shall be called before any allocation happens */ -int -rte_kni_init(unsigned int max_kni_ifaces __rte_unused) -{ - RTE_LOG(WARNING, KNI, "WARNING: KNI is deprecated and will be removed in DPDK 23.11\n"); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 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, - RTE_MEMZONE_IOVA_CONTIG); - 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, - RTE_MEMZONE_IOVA_CONTIG); - 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, - RTE_MEMZONE_IOVA_CONTIG); - 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, - RTE_MEMZONE_IOVA_CONTIG); - 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, - RTE_MEMZONE_IOVA_CONTIG); - 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, - RTE_MEMZONE_IOVA_CONTIG); - KNI_MEM_CHECK(kni->m_resp_q == NULL, resp_q_fail); - - snprintf(mz_name, RTE_MEMZONE_NAMESIZE, KNI_SYNC_ADDR_MZ_NAME_FMT, kni->name); - kni->m_sync_addr = rte_memzone_reserve(mz_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, - RTE_MEMZONE_IOVA_CONTIG); - KNI_MEM_CHECK(kni->m_sync_addr == NULL, sync_addr_fail); - - return 0; - -sync_addr_fail: - rte_memzone_free(kni->m_resp_q); -resp_q_fail: - rte_memzone_free(kni->m_req_q); -req_q_fail: - rte_memzone_free(kni->m_free_q); -free_q_fail: - rte_memzone_free(kni->m_alloc_q); -alloc_q_fail: - rte_memzone_free(kni->m_rx_q); -rx_q_fail: - rte_memzone_free(kni->m_tx_q); -tx_q_fail: - return -1; -} - -static void -kni_release_mz(struct rte_kni *kni) -{ - rte_memzone_free(kni->m_tx_q); - rte_memzone_free(kni->m_rx_q); - rte_memzone_free(kni->m_alloc_q); - rte_memzone_free(kni->m_free_q); - rte_memzone_free(kni->m_req_q); - rte_memzone_free(kni->m_resp_q); - rte_memzone_free(kni->m_sync_addr); -} - -struct rte_kni * -rte_kni_alloc(struct rte_mempool *pktmbuf_pool, - const struct rte_kni_conf *conf, - struct rte_kni_ops *ops) -{ - int ret; - struct rte_kni_device_info dev_info; - struct rte_kni *kni; - struct rte_tailq_entry *te; - struct rte_kni_list *kni_list; - - if (!pktmbuf_pool || !conf || !conf->name[0]) - return NULL; - - /* Check if KNI subsystem has been initialized */ - if (kni_fd < 0) { - RTE_LOG(ERR, KNI, "KNI subsystem has not been initialized. Invoke rte_kni_init() first\n"); - return NULL; - } - - rte_mcfg_tailq_write_lock(); - - kni = __rte_kni_get(conf->name); - if (kni != NULL) { - RTE_LOG(ERR, KNI, "KNI already exists\n"); - goto unlock; - } - - te = rte_zmalloc("KNI_TAILQ_ENTRY", sizeof(*te), 0); - if (te == NULL) { - RTE_LOG(ERR, KNI, "Failed to allocate tailq entry\n"); - goto unlock; - } - - kni = rte_zmalloc("KNI", sizeof(struct rte_kni), RTE_CACHE_LINE_SIZE); - if (kni == NULL) { - RTE_LOG(ERR, KNI, "KNI memory allocation failed\n"); - goto kni_fail; - } - - strlcpy(kni->name, conf->name, RTE_KNI_NAMESIZE); - - if (ops) - memcpy(&kni->ops, ops, sizeof(struct rte_kni_ops)); - else - kni->ops.port_id = UINT16_MAX; - - memset(&dev_info, 0, sizeof(dev_info)); - dev_info.core_id = conf->core_id; - dev_info.force_bind = conf->force_bind; - dev_info.group_id = conf->group_id; - dev_info.mbuf_size = conf->mbuf_size; - dev_info.mtu = conf->mtu; - dev_info.min_mtu = conf->min_mtu; - dev_info.max_mtu = conf->max_mtu; - - memcpy(dev_info.mac_addr, conf->mac_addr, RTE_ETHER_ADDR_LEN); - - strlcpy(dev_info.name, conf->name, RTE_KNI_NAMESIZE); - - ret = kni_reserve_mz(kni); - if (ret < 0) - goto mz_fail; - - /* TX RING */ - kni->tx_q = kni->m_tx_q->addr; - kni_fifo_init(kni->tx_q, KNI_FIFO_COUNT_MAX); - dev_info.tx_phys = kni->m_tx_q->iova; - - /* RX RING */ - kni->rx_q = kni->m_rx_q->addr; - kni_fifo_init(kni->rx_q, KNI_FIFO_COUNT_MAX); - dev_info.rx_phys = kni->m_rx_q->iova; - - /* ALLOC RING */ - kni->alloc_q = kni->m_alloc_q->addr; - kni_fifo_init(kni->alloc_q, KNI_FIFO_COUNT_MAX); - dev_info.alloc_phys = kni->m_alloc_q->iova; - - /* FREE RING */ - kni->free_q = kni->m_free_q->addr; - kni_fifo_init(kni->free_q, KNI_FIFO_COUNT_MAX); - dev_info.free_phys = kni->m_free_q->iova; - - /* Request RING */ - kni->req_q = kni->m_req_q->addr; - kni_fifo_init(kni->req_q, KNI_FIFO_COUNT_MAX); - dev_info.req_phys = kni->m_req_q->iova; - - /* Response RING */ - kni->resp_q = kni->m_resp_q->addr; - kni_fifo_init(kni->resp_q, KNI_FIFO_COUNT_MAX); - dev_info.resp_phys = kni->m_resp_q->iova; - - /* Req/Resp sync mem area */ - kni->sync_addr = kni->m_sync_addr->addr; - dev_info.sync_va = kni->m_sync_addr->addr; - dev_info.sync_phys = kni->m_sync_addr->iova; - - kni->pktmbuf_pool = 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; - - te->data = kni; - - kni_list = RTE_TAILQ_CAST(rte_kni_tailq.head, rte_kni_list); - TAILQ_INSERT_TAIL(kni_list, te, next); - - rte_mcfg_tailq_write_unlock(); - - /* Allocate mbufs and then put them into alloc_q */ - kni_allocate_mbufs(kni); - - return kni; - -ioctl_fail: - kni_release_mz(kni); -mz_fail: - rte_free(kni); -kni_fail: - rte_free(te); -unlock: - rte_mcfg_tailq_write_unlock(); - - return NULL; -} - -static void -kni_free_fifo(struct rte_kni_fifo *fifo) -{ - int ret; - struct rte_mbuf *pkt; - - do { - ret = kni_fifo_get(fifo, (void **)&pkt, 1); - if (ret) - rte_pktmbuf_free(pkt); - } while (ret); -} - -static void * -va2pa(struct rte_mbuf *m) -{ - return (void *)((unsigned long)m - - ((unsigned long)m->buf_addr - (unsigned long)rte_mbuf_iova_get(m))); -} - -static void * -va2pa_all(struct rte_mbuf *mbuf) -{ - void *phy_mbuf = va2pa(mbuf); - struct rte_mbuf *next = mbuf->next; - while (next) { - mbuf->next = va2pa(next); - mbuf = next; - next = mbuf->next; - } - return phy_mbuf; -} - -static void -obj_free(struct rte_mempool *mp __rte_unused, void *opaque, void *obj, - unsigned obj_idx __rte_unused) -{ - struct rte_mbuf *m = obj; - void *mbuf_phys = opaque; - - if (va2pa(m) == mbuf_phys) - rte_pktmbuf_free(m); -} - -static void -kni_free_fifo_phy(struct rte_mempool *mp, struct rte_kni_fifo *fifo) -{ - void *mbuf_phys; - int ret; - - do { - ret = kni_fifo_get(fifo, &mbuf_phys, 1); - if (ret) - rte_mempool_obj_iter(mp, obj_free, mbuf_phys); - } while (ret); -} - -int -rte_kni_release(struct rte_kni *kni) -{ - struct rte_tailq_entry *te; - struct rte_kni_list *kni_list; - struct rte_kni_device_info dev_info; - uint32_t retry = 5; - - if (!kni) - return -1; - - kni_list = RTE_TAILQ_CAST(rte_kni_tailq.head, rte_kni_list); - - rte_mcfg_tailq_write_lock(); - - TAILQ_FOREACH(te, kni_list, next) { - if (te->data == kni) - break; - } - - if (te == NULL) - goto unlock; - - strlcpy(dev_info.name, kni->name, sizeof(dev_info.name)); - if (ioctl(kni_fd, RTE_KNI_IOCTL_RELEASE, &dev_info) < 0) { - RTE_LOG(ERR, KNI, "Fail to release kni device\n"); - goto unlock; - } - - TAILQ_REMOVE(kni_list, te, next); - - rte_mcfg_tailq_write_unlock(); - - /* mbufs in all fifo should be released, except request/response */ - - /* wait until all rxq packets processed by kernel */ - while (kni_fifo_count(kni->rx_q) && retry--) - usleep(1000); - - if (kni_fifo_count(kni->rx_q)) - RTE_LOG(ERR, KNI, "Fail to free all Rx-q items\n"); - - kni_free_fifo_phy(kni->pktmbuf_pool, kni->alloc_q); - kni_free_fifo(kni->tx_q); - kni_free_fifo(kni->free_q); - - kni_release_mz(kni); - - rte_free(kni); - - rte_free(te); - - return 0; - -unlock: - rte_mcfg_tailq_write_unlock(); - - return -1; -} - -/* default callback for request of configuring device mac address */ -static int -kni_config_mac_address(uint16_t port_id, uint8_t mac_addr[]) -{ - int ret = 0; - - if (!rte_eth_dev_is_valid_port(port_id)) { - RTE_LOG(ERR, KNI, "Invalid port id %d\n", port_id); - return -EINVAL; - } - - RTE_LOG(INFO, KNI, "Configure mac address of %d", port_id); - - ret = rte_eth_dev_default_mac_addr_set(port_id, - (struct rte_ether_addr *)mac_addr); - if (ret < 0) - RTE_LOG(ERR, KNI, "Failed to config mac_addr for port %d\n", - port_id); - - return ret; -} - -/* default callback for request of configuring promiscuous mode */ -static int -kni_config_promiscusity(uint16_t port_id, uint8_t to_on) -{ - int ret; - - if (!rte_eth_dev_is_valid_port(port_id)) { - RTE_LOG(ERR, KNI, "Invalid port id %d\n", port_id); - return -EINVAL; - } - - RTE_LOG(INFO, KNI, "Configure promiscuous mode of %d to %d\n", - port_id, to_on); - - if (to_on) - ret = rte_eth_promiscuous_enable(port_id); - else - ret = rte_eth_promiscuous_disable(port_id); - - if (ret != 0) - RTE_LOG(ERR, KNI, - "Failed to %s promiscuous mode for port %u: %s\n", - to_on ? "enable" : "disable", port_id, - rte_strerror(-ret)); - - return ret; -} - -/* default callback for request of configuring allmulticast mode */ -static int -kni_config_allmulticast(uint16_t port_id, uint8_t to_on) -{ - int ret; - - if (!rte_eth_dev_is_valid_port(port_id)) { - RTE_LOG(ERR, KNI, "Invalid port id %d\n", port_id); - return -EINVAL; - } - - RTE_LOG(INFO, KNI, "Configure allmulticast mode of %d to %d\n", - port_id, to_on); - - if (to_on) - ret = rte_eth_allmulticast_enable(port_id); - else - ret = rte_eth_allmulticast_disable(port_id); - if (ret != 0) - RTE_LOG(ERR, KNI, - "Failed to %s allmulticast mode for port %u: %s\n", - to_on ? "enable" : "disable", port_id, - rte_strerror(-ret)); - - return ret; -} - -int -rte_kni_handle_request(struct rte_kni *kni) -{ - unsigned int ret; - struct rte_kni_request *req = NULL; - - if (kni == NULL) - return -1; - - /* Get request mbuf */ - ret = kni_fifo_get(kni->req_q, (void **)&req, 1); - if (ret != 1) - return 0; /* It is OK of can not getting the request mbuf */ - - if (req != kni->sync_addr) { - RTE_LOG(ERR, KNI, "Wrong req pointer %p\n", req); - return -1; - } - - /* Analyze the request and call the relevant actions for it */ - switch (req->req_id) { - case RTE_KNI_REQ_CHANGE_MTU: /* Change MTU */ - if (kni->ops.change_mtu) - req->result = kni->ops.change_mtu(kni->ops.port_id, - req->new_mtu); - break; - case RTE_KNI_REQ_CFG_NETWORK_IF: /* Set network interface up/down */ - if (kni->ops.config_network_if) - req->result = kni->ops.config_network_if(kni->ops.port_id, - req->if_up); - break; - case RTE_KNI_REQ_CHANGE_MAC_ADDR: /* Change MAC Address */ - if (kni->ops.config_mac_address) - req->result = kni->ops.config_mac_address( - kni->ops.port_id, req->mac_addr); - else if (kni->ops.port_id != UINT16_MAX) - req->result = kni_config_mac_address( - kni->ops.port_id, req->mac_addr); - break; - case RTE_KNI_REQ_CHANGE_PROMISC: /* Change PROMISCUOUS MODE */ - if (kni->ops.config_promiscusity) - req->result = kni->ops.config_promiscusity( - kni->ops.port_id, req->promiscusity); - else if (kni->ops.port_id != UINT16_MAX) - req->result = kni_config_promiscusity( - kni->ops.port_id, req->promiscusity); - break; - case RTE_KNI_REQ_CHANGE_ALLMULTI: /* Change ALLMULTICAST MODE */ - if (kni->ops.config_allmulticast) - req->result = kni->ops.config_allmulticast( - kni->ops.port_id, req->allmulti); - else if (kni->ops.port_id != UINT16_MAX) - req->result = kni_config_allmulticast( - kni->ops.port_id, req->allmulti); - break; - default: - RTE_LOG(ERR, KNI, "Unknown request id %u\n", req->req_id); - req->result = -EINVAL; - break; - } - - /* if needed, construct response buffer and put it back to resp_q */ - if (!req->async) - ret = kni_fifo_put(kni->resp_q, (void **)&req, 1); - else - ret = 1; - if (ret != 1) { - RTE_LOG(ERR, KNI, "Fail to put the muf back to resp_q\n"); - return -1; /* It is an error of can't putting the mbuf back */ - } - - return 0; -} - -unsigned -rte_kni_tx_burst(struct rte_kni *kni, struct rte_mbuf **mbufs, unsigned int num) -{ - num = RTE_MIN(kni_fifo_free_count(kni->rx_q), num); - void *phy_mbufs[num]; - unsigned int ret; - unsigned int i; - - for (i = 0; i < num; i++) - phy_mbufs[i] = va2pa_all(mbufs[i]); - - ret = kni_fifo_put(kni->rx_q, phy_mbufs, num); - - /* Get mbufs from free_q and then free them */ - kni_free_mbufs(kni); - - return ret; -} - -unsigned -rte_kni_rx_burst(struct rte_kni *kni, struct rte_mbuf **mbufs, unsigned int num) -{ - unsigned int ret = kni_fifo_get(kni->tx_q, (void **)mbufs, num); - - /* If buffers removed or alloc_q is empty, allocate mbufs and then put them into alloc_q */ - if (ret || (kni_fifo_count(kni->alloc_q) == 0)) - kni_allocate_mbufs(kni); - - return ret; -} - -static void -kni_free_mbufs(struct rte_kni *kni) -{ - int i, ret; - struct rte_mbuf *pkts[MAX_MBUF_BURST_NUM]; - - ret = kni_fifo_get(kni->free_q, (void **)pkts, MAX_MBUF_BURST_NUM); - if (likely(ret > 0)) { - for (i = 0; i < ret; i++) - rte_pktmbuf_free(pkts[i]); - } -} - -static void -kni_allocate_mbufs(struct rte_kni *kni) -{ - int i, ret; - struct rte_mbuf *pkts[MAX_MBUF_BURST_NUM]; - void *phys[MAX_MBUF_BURST_NUM]; - int allocq_free; - - RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, pool) != - offsetof(struct rte_kni_mbuf, pool)); - RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, buf_addr) != - offsetof(struct rte_kni_mbuf, buf_addr)); - RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, next) != - offsetof(struct rte_kni_mbuf, next)); - RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, data_off) != - offsetof(struct rte_kni_mbuf, data_off)); - RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, data_len) != - offsetof(struct rte_kni_mbuf, data_len)); - RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, pkt_len) != - offsetof(struct rte_kni_mbuf, pkt_len)); - RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, ol_flags) != - offsetof(struct rte_kni_mbuf, ol_flags)); - - /* Check if pktmbuf pool has been configured */ - if (kni->pktmbuf_pool == NULL) { - RTE_LOG(ERR, KNI, "No valid mempool for allocating mbufs\n"); - return; - } - - allocq_free = kni_fifo_free_count(kni->alloc_q); - allocq_free = (allocq_free > MAX_MBUF_BURST_NUM) ? - MAX_MBUF_BURST_NUM : allocq_free; - for (i = 0; i < allocq_free; i++) { - pkts[i] = rte_pktmbuf_alloc(kni->pktmbuf_pool); - if (unlikely(pkts[i] == NULL)) { - /* Out of memory */ - RTE_LOG(ERR, KNI, "Out of memory\n"); - break; - } - phys[i] = va2pa(pkts[i]); - } - - /* No pkt mbuf allocated */ - if (i <= 0) - return; - - ret = kni_fifo_put(kni->alloc_q, phys, i); - - /* Check if any mbufs not put into alloc_q, and then free them */ - if (ret >= 0 && ret < i && ret < MAX_MBUF_BURST_NUM) { - int j; - - for (j = ret; j < i; j++) - rte_pktmbuf_free(pkts[j]); - } -} - -struct rte_kni * -rte_kni_get(const char *name) -{ - struct rte_kni *kni; - - if (name == NULL || name[0] == '\0') - return NULL; - - rte_mcfg_tailq_read_lock(); - - kni = __rte_kni_get(name); - - rte_mcfg_tailq_read_unlock(); - - return kni; -} - -const char * -rte_kni_get_name(const struct rte_kni *kni) -{ - return kni->name; -} - -static enum kni_ops_status -kni_check_request_register(struct rte_kni_ops *ops) -{ - /* check if KNI request ops has been registered*/ - if (ops == NULL) - return KNI_REQ_NO_REGISTER; - - if (ops->change_mtu == NULL - && ops->config_network_if == NULL - && ops->config_mac_address == NULL - && ops->config_promiscusity == NULL - && ops->config_allmulticast == NULL) - return KNI_REQ_NO_REGISTER; - - return KNI_REQ_REGISTERED; -} - -int -rte_kni_register_handlers(struct rte_kni *kni, struct rte_kni_ops *ops) -{ - enum kni_ops_status req_status; - - if (ops == NULL) { - RTE_LOG(ERR, KNI, "Invalid KNI request operation.\n"); - return -1; - } - - if (kni == NULL) { - RTE_LOG(ERR, KNI, "Invalid kni info.\n"); - return -1; - } - - req_status = kni_check_request_register(&kni->ops); - if (req_status == KNI_REQ_REGISTERED) { - RTE_LOG(ERR, KNI, "The KNI request operation has already registered.\n"); - return -1; - } - - memcpy(&kni->ops, ops, sizeof(struct rte_kni_ops)); - return 0; -} - -int -rte_kni_unregister_handlers(struct rte_kni *kni) -{ - if (kni == NULL) { - RTE_LOG(ERR, KNI, "Invalid kni info.\n"); - return -1; - } - - memset(&kni->ops, 0, sizeof(struct rte_kni_ops)); - - return 0; -} - -int -rte_kni_update_link(struct rte_kni *kni, unsigned int linkup) -{ - char path[64]; - char old_carrier[2]; - const char *new_carrier; - int old_linkup; - int fd, ret; - - if (kni == NULL) - return -1; - - snprintf(path, sizeof(path), "/sys/devices/virtual/net/%s/carrier", - kni->name); - - fd = open(path, O_RDWR); - if (fd == -1) { - RTE_LOG(ERR, KNI, "Failed to open file: %s.\n", path); - return -1; - } - - ret = read(fd, old_carrier, 2); - if (ret < 1) { - close(fd); - return -1; - } - old_linkup = (old_carrier[0] == '1'); - - if (old_linkup == (int)linkup) - goto out; - - new_carrier = linkup ? "1" : "0"; - ret = write(fd, new_carrier, 1); - if (ret < 1) { - RTE_LOG(ERR, KNI, "Failed to write file: %s.\n", path); - close(fd); - return -1; - } -out: - close(fd); - return old_linkup; -} - -void -rte_kni_close(void) -{ - if (kni_fd < 0) - return; - - close(kni_fd); - kni_fd = -1; -} diff --git a/lib/kni/rte_kni.h b/lib/kni/rte_kni.h deleted file mode 100644 index 1e508acc829b..000000000000 --- a/lib/kni/rte_kni.h +++ /dev/null @@ -1,269 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation - */ - -#ifndef _RTE_KNI_H_ -#define _RTE_KNI_H_ - -/** - * @file - * RTE KNI - * - * The KNI library provides the ability to create and destroy kernel NIC - * interfaces that may be used by the RTE application to receive/transmit - * packets from/to Linux kernel net interfaces. - * - * This library provides two APIs to burst receive packets from KNI interfaces, - * and burst transmit packets to KNI interfaces. - */ - -#include -#include -#include - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct rte_kni; -struct rte_mbuf; - -/** - * Structure which has the function pointers for KNI interface. - */ -struct rte_kni_ops { - uint16_t port_id; /* Port ID */ - - /* Pointer to function of changing MTU */ - int (*change_mtu)(uint16_t port_id, unsigned int new_mtu); - - /* Pointer to function of configuring network interface */ - int (*config_network_if)(uint16_t port_id, uint8_t if_up); - - /* Pointer to function of configuring mac address */ - int (*config_mac_address)(uint16_t port_id, uint8_t mac_addr[]); - - /* Pointer to function of configuring promiscuous mode */ - int (*config_promiscusity)(uint16_t port_id, uint8_t to_on); - - /* Pointer to function of configuring allmulticast mode */ - int (*config_allmulticast)(uint16_t port_id, uint8_t to_on); -}; - -/** - * Structure for configuring KNI device. - */ -struct rte_kni_conf { - /* - * KNI name which will be used in relevant network device. - * Let the name as short as possible, as it will be part of - * memzone name. - */ - char name[RTE_KNI_NAMESIZE]; - uint32_t core_id; /* Core ID to bind kernel thread on */ - uint16_t group_id; /* Group ID */ - unsigned mbuf_size; /* mbuf size */ - struct rte_pci_addr addr; /* deprecated */ - struct rte_pci_id id; /* deprecated */ - - __extension__ - uint8_t force_bind : 1; /* Flag to bind kernel thread */ - uint8_t mac_addr[RTE_ETHER_ADDR_LEN]; /* MAC address assigned to KNI */ - uint16_t mtu; - uint16_t min_mtu; - uint16_t max_mtu; -}; - -/** - * Initialize and preallocate KNI subsystem - * - * This function is to be executed on the main lcore only, after EAL - * initialization and before any KNI interface is attempted to be - * allocated - * - * @param max_kni_ifaces - * The maximum number of KNI interfaces that can coexist concurrently - * - * @return - * - 0 indicates success. - * - negative value indicates failure. - */ -int rte_kni_init(unsigned int max_kni_ifaces); - - -/** - * Allocate KNI interface according to the port id, mbuf size, mbuf pool, - * configurations and callbacks for kernel requests.The KNI interface created - * in the kernel space is the net interface the traditional Linux application - * talking to. - * - * The rte_kni_alloc shall not be called before rte_kni_init() has been - * called. rte_kni_alloc is thread safe. - * - * The mempool should have capacity of more than "2 x KNI_FIFO_COUNT_MAX" - * elements for each KNI interface allocated. - * - * @param pktmbuf_pool - * The mempool for allocating mbufs for packets. - * @param conf - * The pointer to the configurations of the KNI device. - * @param ops - * The pointer to the callbacks for the KNI kernel requests. - * - * @return - * - The pointer to the context of a KNI interface. - * - NULL indicate error. - */ -struct rte_kni *rte_kni_alloc(struct rte_mempool *pktmbuf_pool, - const struct rte_kni_conf *conf, struct rte_kni_ops *ops); - -/** - * Release KNI interface according to the context. It will also release the - * paired KNI interface in kernel space. All processing on the specific KNI - * context need to be stopped before calling this interface. - * - * rte_kni_release is thread safe. - * - * @param kni - * The pointer to the context of an existent KNI interface. - * - * @return - * - 0 indicates success. - * - negative value indicates failure. - */ -int rte_kni_release(struct rte_kni *kni); - -/** - * It is used to handle the request mbufs sent from kernel space. - * Then analyzes it and calls the specific actions for the specific requests. - * Finally constructs the response mbuf and puts it back to the resp_q. - * - * @param kni - * The pointer to the context of an existent KNI interface. - * - * @return - * - 0 - * - negative value indicates failure. - */ -int rte_kni_handle_request(struct rte_kni *kni); - -/** - * Retrieve a burst of packets from a KNI interface. The retrieved packets are - * stored in rte_mbuf structures whose pointers are supplied in the array of - * mbufs, and the maximum number is indicated by num. It handles allocating - * the mbufs for KNI interface alloc queue. - * - * @param kni - * The KNI interface context. - * @param mbufs - * The array to store the pointers of mbufs. - * @param num - * The maximum number per burst. - * - * @return - * The actual number of packets retrieved. - */ -unsigned rte_kni_rx_burst(struct rte_kni *kni, struct rte_mbuf **mbufs, - unsigned num); - -/** - * Send a burst of packets to a KNI interface. The packets to be sent out are - * stored in rte_mbuf structures whose pointers are supplied in the array of - * mbufs, and the maximum number is indicated by num. It handles the freeing of - * the mbufs in the free queue of KNI interface. - * - * @param kni - * The KNI interface context. - * @param mbufs - * The array to store the pointers of mbufs. - * @param num - * The maximum number per burst. - * - * @return - * The actual number of packets sent. - */ -unsigned rte_kni_tx_burst(struct rte_kni *kni, struct rte_mbuf **mbufs, - unsigned num); - -/** - * Get the KNI context of its name. - * - * @param name - * pointer to the KNI device name. - * - * @return - * On success: Pointer to KNI interface. - * On failure: NULL. - */ -struct rte_kni *rte_kni_get(const char *name); - -/** - * Get the name given to a KNI device - * - * @param kni - * The KNI instance to query - * @return - * The pointer to the KNI name - */ -const char *rte_kni_get_name(const struct rte_kni *kni); - -/** - * Register KNI request handling for a specified port,and it can - * be called by primary process or secondary process. - * - * @param kni - * pointer to struct rte_kni. - * @param ops - * pointer to struct rte_kni_ops. - * - * @return - * On success: 0 - * On failure: -1 - */ -int rte_kni_register_handlers(struct rte_kni *kni, struct rte_kni_ops *ops); - -/** - * Unregister KNI request handling for a specified port. - * - * @param kni - * pointer to struct rte_kni. - * - * @return - * On success: 0 - * On failure: -1 - */ -int rte_kni_unregister_handlers(struct rte_kni *kni); - -/** - * Update link carrier state for KNI port. - * - * Update the linkup/linkdown state of a KNI interface in the kernel. - * - * @param kni - * pointer to struct rte_kni. - * @param linkup - * New link state: - * 0 for linkdown. - * > 0 for linkup. - * - * @return - * On failure: -1 - * Previous link state == linkdown: 0 - * Previous link state == linkup: 1 - */ -__rte_experimental -int -rte_kni_update_link(struct rte_kni *kni, unsigned int linkup); - -/** - * Close KNI device. - */ -void rte_kni_close(void); - -#ifdef __cplusplus -} -#endif - -#endif /* _RTE_KNI_H_ */ diff --git a/lib/kni/rte_kni_common.h b/lib/kni/rte_kni_common.h deleted file mode 100644 index 8d3ee0fa4fc2..000000000000 --- a/lib/kni/rte_kni_common.h +++ /dev/null @@ -1,147 +0,0 @@ -/* SPDX-License-Identifier: (BSD-3-Clause OR LGPL-2.1) */ -/* - * Copyright(c) 2007-2014 Intel Corporation. - */ - -#ifndef _RTE_KNI_COMMON_H_ -#define _RTE_KNI_COMMON_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __KERNEL__ -#include -#include -#define RTE_STD_C11 -#else -#include -#include -#endif - -/* - * KNI name is part of memzone name. Must not exceed IFNAMSIZ. - */ -#define RTE_KNI_NAMESIZE 16 - -#define RTE_CACHE_LINE_MIN_SIZE 64 - -/* - * Request id. - */ -enum rte_kni_req_id { - RTE_KNI_REQ_UNKNOWN = 0, - RTE_KNI_REQ_CHANGE_MTU, - RTE_KNI_REQ_CFG_NETWORK_IF, - RTE_KNI_REQ_CHANGE_MAC_ADDR, - RTE_KNI_REQ_CHANGE_PROMISC, - RTE_KNI_REQ_CHANGE_ALLMULTI, - RTE_KNI_REQ_MAX, -}; - -/* - * Structure for KNI request. - */ -struct rte_kni_request { - uint32_t req_id; /**< Request id */ - RTE_STD_C11 - union { - uint32_t new_mtu; /**< New MTU */ - uint8_t if_up; /**< 1: interface up, 0: interface down */ - uint8_t mac_addr[6]; /**< MAC address for interface */ - uint8_t promiscusity;/**< 1: promisc mode enable, 0: disable */ - uint8_t allmulti; /**< 1: all-multicast mode enable, 0: disable */ - }; - int32_t async : 1; /**< 1: request is asynchronous */ - int32_t result; /**< Result for processing request */ -} __attribute__((__packed__)); - -/* - * Fifo struct mapped in a shared memory. It describes a circular buffer FIFO - * Write and read should wrap around. Fifo is empty when write == read - * Writing should never overwrite the read position - */ -struct rte_kni_fifo { -#ifdef RTE_USE_C11_MEM_MODEL - unsigned write; /**< Next position to be written*/ - unsigned read; /**< Next position to be read */ -#else - volatile unsigned write; /**< Next position to be written*/ - volatile unsigned read; /**< Next position to be read */ -#endif - unsigned len; /**< Circular buffer length */ - unsigned elem_size; /**< Pointer size - for 32/64 bit OS */ - void *volatile buffer[]; /**< The buffer contains mbuf pointers */ -}; - -/* - * The kernel image of the rte_mbuf struct, with only the relevant fields. - * Padding is necessary to assure the offsets of these fields - */ -struct rte_kni_mbuf { - void *buf_addr __attribute__((__aligned__(RTE_CACHE_LINE_SIZE))); - uint64_t buf_iova; - uint16_t data_off; /**< Start address of data in segment buffer. */ - char pad1[2]; - uint16_t nb_segs; /**< Number of segments. */ - char pad4[2]; - uint64_t ol_flags; /**< Offload features. */ - char pad2[4]; - uint32_t pkt_len; /**< Total pkt len: sum of all segment data_len. */ - uint16_t data_len; /**< Amount of data in segment buffer. */ - char pad3[14]; - void *pool; - - /* fields on second cache line */ - __attribute__((__aligned__(RTE_CACHE_LINE_MIN_SIZE))) - void *next; /**< Physical address of next mbuf in kernel. */ -}; - -/* - * Struct used to create a KNI device. Passed to the kernel in IOCTL call - */ - -struct rte_kni_device_info { - char name[RTE_KNI_NAMESIZE]; /**< Network device name for KNI */ - - phys_addr_t tx_phys; - phys_addr_t rx_phys; - phys_addr_t alloc_phys; - phys_addr_t free_phys; - - /* Used by Ethtool */ - phys_addr_t req_phys; - phys_addr_t resp_phys; - phys_addr_t sync_phys; - void * sync_va; - - /* mbuf mempool */ - void * mbuf_va; - phys_addr_t mbuf_phys; - - uint16_t group_id; /**< Group ID */ - uint32_t core_id; /**< core ID to bind for kernel thread */ - - __extension__ - uint8_t force_bind : 1; /**< Flag for kernel thread binding */ - - /* mbuf size */ - unsigned mbuf_size; - unsigned int mtu; - unsigned int min_mtu; - unsigned int max_mtu; - uint8_t mac_addr[6]; - uint8_t iova_mode; -}; - -#define KNI_DEVICE "kni" - -#define RTE_KNI_IOCTL_TEST _IOWR(0, 1, int) -#define RTE_KNI_IOCTL_CREATE _IOWR(0, 2, struct rte_kni_device_info) -#define RTE_KNI_IOCTL_RELEASE _IOWR(0, 3, struct rte_kni_device_info) - -#ifdef __cplusplus -} -#endif - -#endif /* _RTE_KNI_COMMON_H_ */ diff --git a/lib/kni/rte_kni_fifo.h b/lib/kni/rte_kni_fifo.h deleted file mode 100644 index d2ec82fe87fc..000000000000 --- a/lib/kni/rte_kni_fifo.h +++ /dev/null @@ -1,117 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation - */ - - - -/** - * @internal when c11 memory model enabled use c11 atomic memory barrier. - * when under non c11 memory model use rte_smp_* memory barrier. - * - * @param src - * Pointer to the source data. - * @param dst - * Pointer to the destination data. - * @param value - * Data value. - */ -#ifdef RTE_USE_C11_MEM_MODEL -#define __KNI_LOAD_ACQUIRE(src) ({ \ - __atomic_load_n((src), __ATOMIC_ACQUIRE); \ - }) -#define __KNI_STORE_RELEASE(dst, value) do { \ - __atomic_store_n((dst), value, __ATOMIC_RELEASE); \ - } while(0) -#else -#define __KNI_LOAD_ACQUIRE(src) ({ \ - typeof (*(src)) val = *(src); \ - rte_smp_rmb(); \ - val; \ - }) -#define __KNI_STORE_RELEASE(dst, value) do { \ - *(dst) = value; \ - rte_smp_wmb(); \ - } while(0) -#endif - -/** - * Initializes the kni fifo structure - */ -static void -kni_fifo_init(struct rte_kni_fifo *fifo, unsigned size) -{ - /* Ensure size is power of 2 */ - if (size & (size - 1)) - rte_panic("KNI fifo size must be power of 2\n"); - - fifo->write = 0; - fifo->read = 0; - fifo->len = size; - fifo->elem_size = sizeof(void *); -} - -/** - * Adds num elements into the fifo. Return the number actually written - */ -static inline unsigned -kni_fifo_put(struct rte_kni_fifo *fifo, void **data, unsigned num) -{ - unsigned i = 0; - unsigned fifo_write = fifo->write; - unsigned new_write = fifo_write; - unsigned fifo_read = __KNI_LOAD_ACQUIRE(&fifo->read); - - for (i = 0; i < num; i++) { - new_write = (new_write + 1) & (fifo->len - 1); - - if (new_write == fifo_read) - break; - fifo->buffer[fifo_write] = data[i]; - fifo_write = new_write; - } - __KNI_STORE_RELEASE(&fifo->write, fifo_write); - return i; -} - -/** - * Get up to num elements from the fifo. Return the number actually read - */ -static inline unsigned -kni_fifo_get(struct rte_kni_fifo *fifo, void **data, unsigned num) -{ - unsigned i = 0; - unsigned new_read = fifo->read; - unsigned fifo_write = __KNI_LOAD_ACQUIRE(&fifo->write); - - for (i = 0; i < num; i++) { - if (new_read == fifo_write) - break; - - data[i] = fifo->buffer[new_read]; - new_read = (new_read + 1) & (fifo->len - 1); - } - __KNI_STORE_RELEASE(&fifo->read, new_read); - return i; -} - -/** - * Get the num of elements in the fifo - */ -static inline uint32_t -kni_fifo_count(struct rte_kni_fifo *fifo) -{ - unsigned fifo_write = __KNI_LOAD_ACQUIRE(&fifo->write); - unsigned fifo_read = __KNI_LOAD_ACQUIRE(&fifo->read); - return (fifo->len + fifo_write - fifo_read) & (fifo->len - 1); -} - -/** - * Get the num of available elements in the fifo - */ -static inline uint32_t -kni_fifo_free_count(struct rte_kni_fifo *fifo) -{ - uint32_t fifo_write = __KNI_LOAD_ACQUIRE(&fifo->write); - uint32_t fifo_read = __KNI_LOAD_ACQUIRE(&fifo->read); - return (fifo_read - fifo_write - 1) & (fifo->len - 1); -} diff --git a/lib/kni/version.map b/lib/kni/version.map deleted file mode 100644 index 13ffaa5bfd65..000000000000 --- a/lib/kni/version.map +++ /dev/null @@ -1,24 +0,0 @@ -DPDK_24 { - global: - - rte_kni_alloc; - rte_kni_close; - rte_kni_get; - rte_kni_get_name; - rte_kni_handle_request; - rte_kni_init; - rte_kni_register_handlers; - rte_kni_release; - rte_kni_rx_burst; - rte_kni_tx_burst; - rte_kni_unregister_handlers; - - local: *; -}; - -EXPERIMENTAL { - global: - - # updated in v21.08 - rte_kni_update_link; -}; diff --git a/lib/meson.build b/lib/meson.build index ecac701161c8..bbfa28ba86dd 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -39,7 +39,6 @@ libraries = [ 'gso', 'ip_frag', 'jobstats', - 'kni', 'latencystats', 'lpm', 'member', @@ -73,7 +72,6 @@ optional_libs = [ 'graph', 'gro', 'gso', - 'kni', 'jobstats', 'latencystats', 'metrics', @@ -86,10 +84,6 @@ optional_libs = [ 'vhost', ] -dpdk_libs_deprecated += [ - 'kni', -] - disabled_libs = [] opt_disabled_libs = run_command(list_dir_globs, get_option('disable_libs'), check: true).stdout().split() diff --git a/lib/port/meson.build b/lib/port/meson.build index 3ab37e2cb4b7..b0af2b185b39 100644 --- a/lib/port/meson.build +++ b/lib/port/meson.build @@ -45,9 +45,3 @@ if dpdk_conf.has('RTE_HAS_LIBPCAP') dpdk_conf.set('RTE_PORT_PCAP', 1) ext_deps += pcap_dep # dependency provided in config/meson.build endif - -if dpdk_conf.has('RTE_LIB_KNI') - sources += files('rte_port_kni.c') - headers += files('rte_port_kni.h') - deps += 'kni' -endif diff --git a/lib/port/rte_port_kni.c b/lib/port/rte_port_kni.c deleted file mode 100644 index 1c7a6cb200ea..000000000000 --- a/lib/port/rte_port_kni.c +++ /dev/null @@ -1,515 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2016 Ethan Zhuang . - * Copyright(c) 2016 Intel Corporation. - */ -#include - -#include -#include - -#include "rte_port_kni.h" - -/* - * Port KNI Reader - */ -#ifdef RTE_PORT_STATS_COLLECT - -#define RTE_PORT_KNI_READER_STATS_PKTS_IN_ADD(port, val) \ - port->stats.n_pkts_in += val -#define RTE_PORT_KNI_READER_STATS_PKTS_DROP_ADD(port, val) \ - port->stats.n_pkts_drop += val - -#else - -#define RTE_PORT_KNI_READER_STATS_PKTS_IN_ADD(port, val) -#define RTE_PORT_KNI_READER_STATS_PKTS_DROP_ADD(port, val) - -#endif - -struct rte_port_kni_reader { - struct rte_port_in_stats stats; - - struct rte_kni *kni; -}; - -static void * -rte_port_kni_reader_create(void *params, int socket_id) -{ - struct rte_port_kni_reader_params *conf = - params; - struct rte_port_kni_reader *port; - - /* Check input parameters */ - if (conf == NULL) { - RTE_LOG(ERR, PORT, "%s: params is NULL\n", __func__); - return NULL; - } - - /* Memory allocation */ - port = rte_zmalloc_socket("PORT", sizeof(*port), - RTE_CACHE_LINE_SIZE, socket_id); - if (port == NULL) { - RTE_LOG(ERR, PORT, "%s: Failed to allocate port\n", __func__); - return NULL; - } - - /* Initialization */ - port->kni = conf->kni; - - return port; -} - -static int -rte_port_kni_reader_rx(void *port, struct rte_mbuf **pkts, uint32_t n_pkts) -{ - struct rte_port_kni_reader *p = - port; - uint16_t rx_pkt_cnt; - - rx_pkt_cnt = rte_kni_rx_burst(p->kni, pkts, n_pkts); - RTE_PORT_KNI_READER_STATS_PKTS_IN_ADD(p, rx_pkt_cnt); - return rx_pkt_cnt; -} - -static int -rte_port_kni_reader_free(void *port) -{ - if (port == NULL) { - RTE_LOG(ERR, PORT, "%s: port is NULL\n", __func__); - return -EINVAL; - } - - rte_free(port); - - return 0; -} - -static int rte_port_kni_reader_stats_read(void *port, - struct rte_port_in_stats *stats, int clear) -{ - struct rte_port_kni_reader *p = - port; - - if (stats != NULL) - memcpy(stats, &p->stats, sizeof(p->stats)); - - if (clear) - memset(&p->stats, 0, sizeof(p->stats)); - - return 0; -} - -/* - * Port KNI Writer - */ -#ifdef RTE_PORT_STATS_COLLECT - -#define RTE_PORT_KNI_WRITER_STATS_PKTS_IN_ADD(port, val) \ - port->stats.n_pkts_in += val -#define RTE_PORT_KNI_WRITER_STATS_PKTS_DROP_ADD(port, val) \ - port->stats.n_pkts_drop += val - -#else - -#define RTE_PORT_KNI_WRITER_STATS_PKTS_IN_ADD(port, val) -#define RTE_PORT_KNI_WRITER_STATS_PKTS_DROP_ADD(port, val) - -#endif - -struct rte_port_kni_writer { - struct rte_port_out_stats stats; - - struct rte_mbuf *tx_buf[2 * RTE_PORT_IN_BURST_SIZE_MAX]; - uint32_t tx_burst_sz; - uint32_t tx_buf_count; - uint64_t bsz_mask; - struct rte_kni *kni; -}; - -static void * -rte_port_kni_writer_create(void *params, int socket_id) -{ - struct rte_port_kni_writer_params *conf = - params; - struct rte_port_kni_writer *port; - - /* Check input parameters */ - if ((conf == NULL) || - (conf->tx_burst_sz == 0) || - (conf->tx_burst_sz > RTE_PORT_IN_BURST_SIZE_MAX) || - (!rte_is_power_of_2(conf->tx_burst_sz))) { - RTE_LOG(ERR, PORT, "%s: Invalid input parameters\n", __func__); - return NULL; - } - - /* Memory allocation */ - port = rte_zmalloc_socket("PORT", sizeof(*port), - RTE_CACHE_LINE_SIZE, socket_id); - if (port == NULL) { - RTE_LOG(ERR, PORT, "%s: Failed to allocate port\n", __func__); - return NULL; - } - - /* Initialization */ - port->kni = conf->kni; - port->tx_burst_sz = conf->tx_burst_sz; - port->tx_buf_count = 0; - port->bsz_mask = 1LLU << (conf->tx_burst_sz - 1); - - return port; -} - -static inline void -send_burst(struct rte_port_kni_writer *p) -{ - uint32_t nb_tx; - - nb_tx = rte_kni_tx_burst(p->kni, p->tx_buf, p->tx_buf_count); - - RTE_PORT_KNI_WRITER_STATS_PKTS_DROP_ADD(p, p->tx_buf_count - nb_tx); - for (; nb_tx < p->tx_buf_count; nb_tx++) - rte_pktmbuf_free(p->tx_buf[nb_tx]); - - p->tx_buf_count = 0; -} - -static int -rte_port_kni_writer_tx(void *port, struct rte_mbuf *pkt) -{ - struct rte_port_kni_writer *p = - port; - - p->tx_buf[p->tx_buf_count++] = pkt; - RTE_PORT_KNI_WRITER_STATS_PKTS_IN_ADD(p, 1); - if (p->tx_buf_count >= p->tx_burst_sz) - send_burst(p); - - return 0; -} - -static int -rte_port_kni_writer_tx_bulk(void *port, - struct rte_mbuf **pkts, - uint64_t pkts_mask) -{ - struct rte_port_kni_writer *p = - port; - uint64_t bsz_mask = p->bsz_mask; - uint32_t tx_buf_count = p->tx_buf_count; - uint64_t expr = (pkts_mask & (pkts_mask + 1)) | - ((pkts_mask & bsz_mask) ^ bsz_mask); - - if (expr == 0) { - uint64_t n_pkts = __builtin_popcountll(pkts_mask); - uint32_t n_pkts_ok; - - if (tx_buf_count) - send_burst(p); - - RTE_PORT_KNI_WRITER_STATS_PKTS_IN_ADD(p, n_pkts); - n_pkts_ok = rte_kni_tx_burst(p->kni, pkts, n_pkts); - - RTE_PORT_KNI_WRITER_STATS_PKTS_DROP_ADD(p, n_pkts - n_pkts_ok); - for (; n_pkts_ok < n_pkts; n_pkts_ok++) { - struct rte_mbuf *pkt = pkts[n_pkts_ok]; - - rte_pktmbuf_free(pkt); - } - } else { - for (; pkts_mask;) { - uint32_t pkt_index = __builtin_ctzll(pkts_mask); - uint64_t pkt_mask = 1LLU << pkt_index; - struct rte_mbuf *pkt = pkts[pkt_index]; - - p->tx_buf[tx_buf_count++] = pkt; - RTE_PORT_KNI_WRITER_STATS_PKTS_IN_ADD(p, 1); - pkts_mask &= ~pkt_mask; - } - - p->tx_buf_count = tx_buf_count; - if (tx_buf_count >= p->tx_burst_sz) - send_burst(p); - } - - return 0; -} - -static int -rte_port_kni_writer_flush(void *port) -{ - struct rte_port_kni_writer *p = - port; - - if (p->tx_buf_count > 0) - send_burst(p); - - return 0; -} - -static int -rte_port_kni_writer_free(void *port) -{ - if (port == NULL) { - RTE_LOG(ERR, PORT, "%s: Port is NULL\n", __func__); - return -EINVAL; - } - - rte_port_kni_writer_flush(port); - rte_free(port); - - return 0; -} - -static int rte_port_kni_writer_stats_read(void *port, - struct rte_port_out_stats *stats, int clear) -{ - struct rte_port_kni_writer *p = - port; - - if (stats != NULL) - memcpy(stats, &p->stats, sizeof(p->stats)); - - if (clear) - memset(&p->stats, 0, sizeof(p->stats)); - - return 0; -} - -/* - * Port KNI Writer Nodrop - */ -#ifdef RTE_PORT_STATS_COLLECT - -#define RTE_PORT_KNI_WRITER_NODROP_STATS_PKTS_IN_ADD(port, val) \ - port->stats.n_pkts_in += val -#define RTE_PORT_KNI_WRITER_NODROP_STATS_PKTS_DROP_ADD(port, val) \ - port->stats.n_pkts_drop += val - -#else - -#define RTE_PORT_KNI_WRITER_NODROP_STATS_PKTS_IN_ADD(port, val) -#define RTE_PORT_KNI_WRITER_NODROP_STATS_PKTS_DROP_ADD(port, val) - -#endif - -struct rte_port_kni_writer_nodrop { - struct rte_port_out_stats stats; - - struct rte_mbuf *tx_buf[2 * RTE_PORT_IN_BURST_SIZE_MAX]; - uint32_t tx_burst_sz; - uint32_t tx_buf_count; - uint64_t bsz_mask; - uint64_t n_retries; - struct rte_kni *kni; -}; - -static void * -rte_port_kni_writer_nodrop_create(void *params, int socket_id) -{ - struct rte_port_kni_writer_nodrop_params *conf = - params; - struct rte_port_kni_writer_nodrop *port; - - /* Check input parameters */ - if ((conf == NULL) || - (conf->tx_burst_sz == 0) || - (conf->tx_burst_sz > RTE_PORT_IN_BURST_SIZE_MAX) || - (!rte_is_power_of_2(conf->tx_burst_sz))) { - RTE_LOG(ERR, PORT, "%s: Invalid input parameters\n", __func__); - return NULL; - } - - /* Memory allocation */ - port = rte_zmalloc_socket("PORT", sizeof(*port), - RTE_CACHE_LINE_SIZE, socket_id); - if (port == NULL) { - RTE_LOG(ERR, PORT, "%s: Failed to allocate port\n", __func__); - return NULL; - } - - /* Initialization */ - port->kni = conf->kni; - port->tx_burst_sz = conf->tx_burst_sz; - port->tx_buf_count = 0; - port->bsz_mask = 1LLU << (conf->tx_burst_sz - 1); - - /* - * When n_retries is 0 it means that we should wait for every packet to - * send no matter how many retries should it take. To limit number of - * branches in fast path, we use UINT64_MAX instead of branching. - */ - port->n_retries = (conf->n_retries == 0) ? UINT64_MAX : conf->n_retries; - - return port; -} - -static inline void -send_burst_nodrop(struct rte_port_kni_writer_nodrop *p) -{ - uint32_t nb_tx = 0, i; - - nb_tx = rte_kni_tx_burst(p->kni, p->tx_buf, p->tx_buf_count); - - /* We sent all the packets in a first try */ - if (nb_tx >= p->tx_buf_count) { - p->tx_buf_count = 0; - return; - } - - for (i = 0; i < p->n_retries; i++) { - nb_tx += rte_kni_tx_burst(p->kni, - p->tx_buf + nb_tx, - p->tx_buf_count - nb_tx); - - /* We sent all the packets in more than one try */ - if (nb_tx >= p->tx_buf_count) { - p->tx_buf_count = 0; - return; - } - } - - /* We didn't send the packets in maximum allowed attempts */ - RTE_PORT_KNI_WRITER_NODROP_STATS_PKTS_DROP_ADD(p, p->tx_buf_count - nb_tx); - for ( ; nb_tx < p->tx_buf_count; nb_tx++) - rte_pktmbuf_free(p->tx_buf[nb_tx]); - - p->tx_buf_count = 0; -} - -static int -rte_port_kni_writer_nodrop_tx(void *port, struct rte_mbuf *pkt) -{ - struct rte_port_kni_writer_nodrop *p = - port; - - p->tx_buf[p->tx_buf_count++] = pkt; - RTE_PORT_KNI_WRITER_STATS_PKTS_IN_ADD(p, 1); - if (p->tx_buf_count >= p->tx_burst_sz) - send_burst_nodrop(p); - - return 0; -} - -static int -rte_port_kni_writer_nodrop_tx_bulk(void *port, - struct rte_mbuf **pkts, - uint64_t pkts_mask) -{ - struct rte_port_kni_writer_nodrop *p = - port; - - uint64_t bsz_mask = p->bsz_mask; - uint32_t tx_buf_count = p->tx_buf_count; - uint64_t expr = (pkts_mask & (pkts_mask + 1)) | - ((pkts_mask & bsz_mask) ^ bsz_mask); - - if (expr == 0) { - uint64_t n_pkts = __builtin_popcountll(pkts_mask); - uint32_t n_pkts_ok; - - if (tx_buf_count) - send_burst_nodrop(p); - - RTE_PORT_KNI_WRITER_NODROP_STATS_PKTS_IN_ADD(p, n_pkts); - n_pkts_ok = rte_kni_tx_burst(p->kni, pkts, n_pkts); - - if (n_pkts_ok >= n_pkts) - return 0; - - /* - * If we didn't manage to send all packets in single burst, move - * remaining packets to the buffer and call send burst. - */ - for (; n_pkts_ok < n_pkts; n_pkts_ok++) { - struct rte_mbuf *pkt = pkts[n_pkts_ok]; - p->tx_buf[p->tx_buf_count++] = pkt; - } - send_burst_nodrop(p); - } else { - for ( ; pkts_mask; ) { - uint32_t pkt_index = __builtin_ctzll(pkts_mask); - uint64_t pkt_mask = 1LLU << pkt_index; - struct rte_mbuf *pkt = pkts[pkt_index]; - - p->tx_buf[tx_buf_count++] = pkt; - RTE_PORT_KNI_WRITER_NODROP_STATS_PKTS_IN_ADD(p, 1); - pkts_mask &= ~pkt_mask; - } - - p->tx_buf_count = tx_buf_count; - if (tx_buf_count >= p->tx_burst_sz) - send_burst_nodrop(p); - } - - return 0; -} - -static int -rte_port_kni_writer_nodrop_flush(void *port) -{ - struct rte_port_kni_writer_nodrop *p = - port; - - if (p->tx_buf_count > 0) - send_burst_nodrop(p); - - return 0; -} - -static int -rte_port_kni_writer_nodrop_free(void *port) -{ - if (port == NULL) { - RTE_LOG(ERR, PORT, "%s: Port is NULL\n", __func__); - return -EINVAL; - } - - rte_port_kni_writer_nodrop_flush(port); - rte_free(port); - - return 0; -} - -static int rte_port_kni_writer_nodrop_stats_read(void *port, - struct rte_port_out_stats *stats, int clear) -{ - struct rte_port_kni_writer_nodrop *p = - port; - - if (stats != NULL) - memcpy(stats, &p->stats, sizeof(p->stats)); - - if (clear) - memset(&p->stats, 0, sizeof(p->stats)); - - return 0; -} - - -/* - * Summary of port operations - */ -struct rte_port_in_ops rte_port_kni_reader_ops = { - .f_create = rte_port_kni_reader_create, - .f_free = rte_port_kni_reader_free, - .f_rx = rte_port_kni_reader_rx, - .f_stats = rte_port_kni_reader_stats_read, -}; - -struct rte_port_out_ops rte_port_kni_writer_ops = { - .f_create = rte_port_kni_writer_create, - .f_free = rte_port_kni_writer_free, - .f_tx = rte_port_kni_writer_tx, - .f_tx_bulk = rte_port_kni_writer_tx_bulk, - .f_flush = rte_port_kni_writer_flush, - .f_stats = rte_port_kni_writer_stats_read, -}; - -struct rte_port_out_ops rte_port_kni_writer_nodrop_ops = { - .f_create = rte_port_kni_writer_nodrop_create, - .f_free = rte_port_kni_writer_nodrop_free, - .f_tx = rte_port_kni_writer_nodrop_tx, - .f_tx_bulk = rte_port_kni_writer_nodrop_tx_bulk, - .f_flush = rte_port_kni_writer_nodrop_flush, - .f_stats = rte_port_kni_writer_nodrop_stats_read, -}; diff --git a/lib/port/rte_port_kni.h b/lib/port/rte_port_kni.h deleted file mode 100644 index 280f58c121e2..000000000000 --- a/lib/port/rte_port_kni.h +++ /dev/null @@ -1,63 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2016 Ethan Zhuang . - * Copyright(c) 2016 Intel Corporation. - */ - -#ifndef __INCLUDE_RTE_PORT_KNI_H__ -#define __INCLUDE_RTE_PORT_KNI_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @file - * RTE Port KNI Interface - * - * kni_reader: input port built on top of pre-initialized KNI interface - * kni_writer: output port built on top of pre-initialized KNI interface - */ - -#include - -#include "rte_port.h" - -/** kni_reader port parameters */ -struct rte_port_kni_reader_params { - /** KNI interface reference */ - struct rte_kni *kni; -}; - -/** kni_reader port operations */ -extern struct rte_port_in_ops rte_port_kni_reader_ops; - - -/** kni_writer port parameters */ -struct rte_port_kni_writer_params { - /** KNI interface reference */ - struct rte_kni *kni; - /** Burst size to KNI interface. */ - uint32_t tx_burst_sz; -}; - -/** kni_writer port operations */ -extern struct rte_port_out_ops rte_port_kni_writer_ops; - -/** kni_writer_nodrop port parameters */ -struct rte_port_kni_writer_nodrop_params { - /** KNI interface reference */ - struct rte_kni *kni; - /** Burst size to KNI interface. */ - uint32_t tx_burst_sz; - /** Maximum number of retries, 0 for no limit */ - uint32_t n_retries; -}; - -/** kni_writer_nodrop port operations */ -extern struct rte_port_out_ops rte_port_kni_writer_nodrop_ops; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/port/version.map b/lib/port/version.map index 83dbec7b01d2..fefcf29063f6 100644 --- a/lib/port/version.map +++ b/lib/port/version.map @@ -7,9 +7,6 @@ DPDK_24 { rte_port_fd_reader_ops; rte_port_fd_writer_nodrop_ops; rte_port_fd_writer_ops; - rte_port_kni_reader_ops; - rte_port_kni_writer_nodrop_ops; - rte_port_kni_writer_ops; rte_port_ring_multi_reader_ops; rte_port_ring_multi_writer_nodrop_ops; rte_port_ring_multi_writer_ops; diff --git a/meson_options.txt b/meson_options.txt index 95e22e0ce70c..621e1ca9ba8c 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -10,7 +10,7 @@ option('disable_apps', type: 'string', value: '', description: 'Comma-separated list of apps to explicitly disable.') option('disable_drivers', type: 'string', value: '', description: 'Comma-separated list of drivers to explicitly disable.') -option('disable_libs', type: 'string', value: 'kni', description: +option('disable_libs', type: 'string', value: '', description: 'Comma-separated list of libraries to explicitly disable. [NOTE: not all libs can be disabled]') option('drivers_install_subdir', type: 'string', value: 'dpdk/pmds-', description: 'Subdirectory of libdir where to install PMDs. Defaults to using a versioned subdirectory.') -- 2.39.2