From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from NAM03-BY2-obe.outbound.protection.outlook.com (mail-by2nam03on0070.outbound.protection.outlook.com [104.47.42.70]) by dpdk.org (Postfix) with ESMTP id 2A681A48A for ; Mon, 19 Mar 2018 15:55:46 +0100 (CET) Received: from CY4PR03CA0096.namprd03.prod.outlook.com (2603:10b6:910:4d::37) by MWHPR03MB2766.namprd03.prod.outlook.com (2603:10b6:300:48::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.588.14; Mon, 19 Mar 2018 14:55:43 +0000 Received: from BN1AFFO11FD009.protection.gbl (2a01:111:f400:7c10::145) by CY4PR03CA0096.outlook.office365.com (2603:10b6:910:4d::37) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.588.14 via Frontend Transport; Mon, 19 Mar 2018 14:55:43 +0000 Authentication-Results: spf=fail (sender IP is 192.88.168.50) smtp.mailfrom=nxp.com; dpdk.org; dkim=none (message not signed) header.d=none;dpdk.org; dmarc=fail action=none header.from=nxp.com; Received-SPF: Fail (protection.outlook.com: domain of nxp.com does not designate 192.88.168.50 as permitted sender) receiver=protection.outlook.com; client-ip=192.88.168.50; helo=tx30smr01.am.freescale.net; Received: from tx30smr01.am.freescale.net (192.88.168.50) by BN1AFFO11FD009.mail.protection.outlook.com (10.58.52.69) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.20.527.18 via Frontend Transport; Mon, 19 Mar 2018 14:55:43 +0000 Received: from sunil-OptiPlex-790.ap.freescale.net (sunil-OptiPlex-790.ap.freescale.net [10.232.132.53]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id w2JDkDOL023017; Mon, 19 Mar 2018 06:46:14 -0700 From: Sunil Kumar Kori To: CC: , Date: Mon, 19 Mar 2018 19:15:20 +0530 Message-ID: <20180319134520.28155-1-sunil.kori@nxp.com> X-Mailer: git-send-email 2.9.3 X-EOPAttributedMessage: 0 X-Matching-Connectors: 131659449435685376; (91ab9b29-cfa4-454e-5278-08d120cd25b8); () X-Forefront-Antispam-Report: CIP:192.88.168.50; IPV:CAL; CTRY:US; EFV:NLI; SFV:NSPM; SFS:(10009020)(39380400002)(346002)(396003)(39860400002)(376002)(2980300002)(1110001)(1109001)(339900001)(189003)(199004)(1857600001)(50466002)(356003)(106466001)(77096007)(48376002)(85426001)(1076002)(2351001)(26005)(68736007)(86362001)(6916009)(47776003)(4326008)(53936002)(6666003)(97736004)(26826003)(53946003)(336012)(16586007)(5660300001)(316002)(8936002)(50226002)(2906002)(498600001)(305945005)(59450400001)(8676002)(81166006)(81156014)(36756003)(105606002)(51416003)(54906003)(104016004)(579004); DIR:OUT; SFP:1101; SCL:1; SRVR:MWHPR03MB2766; H:tx30smr01.am.freescale.net; FPR:; SPF:Fail; PTR:InfoDomainNonexistent; MX:1; A:1; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; BN1AFFO11FD009; 1:nZaZ2tkk/252eAxme1QjCF3q/Z2hMuQzp4iel0TbkWaph1G3tJk71/LD+2C4ucQRX1vS+3Vd6uakPkEL3NYzThsgZ6Y5zc1N/UQf7ECWpDIryqSHjKmwx+NAk7ndsxrZ MIME-Version: 1.0 Content-Type: text/plain X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 8c511b30-f5e2-40f3-0200-08d58da97d67 X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(7020095)(5600026)(4604075)(2017052603328); SRVR:MWHPR03MB2766; X-Microsoft-Exchange-Diagnostics: 1; MWHPR03MB2766; 3:ZFf893QQCoBbREf6F9xuYPOg8eyzcd7LlqiTAbUDqO3tkdgkLAPZOKgQ1aiU5SFSPZ5jNyvK1ajkRVFZ1/s+JIF8SrR8lUyZCLFlG485pHE6XbmoE/ZbI+PXzgcPNqMKb01gslZrtd9oq0ZQLXOxx014hPe9lHxNd3uWw7hyxlsZuQaZS6KgpWUQ8HCTLT37hpOW4rxrkLINJd2aNSqxqXsxBDMxRyrqM4+G6NEfIuRWyaF8F1AufZddRiej3R4zmAzyD9XhywWoVAGkiVIbIom4guPBV4lE3/VF0ODFIBawzceMR1hfi9MtKUW3vLFq4VAC5qMjyqHPt57izMt0G3+Y9jTbG/UHTByKZDsvfJ0=; 25:CF73AM4jaUkgjsLniB0YOMbFN5l4of6OaCjBGzk3A/gpaT1wc+jISFV9hpKCdn+9sxe3GsZ3trxcWRU5emN0rl4gU2M9/ThkR9p13DeoGVazNF+a2BQ+X254HZ8nO0l0MQasBcNry9y+U/yU26oRObJ2kzcgLre+PdnsTmg4fRA+h4eoTjA/NPWLZjU9aRIrSeorR15MRWm/veOlVyhHRolV45uxJ9DsD+0al/8I+GlHDlx2de+6VkrWjiWhIA1lKjcNMTh1VCqWSl/3Lod3GaSsqZ6wclbSvMPu1uG5oe6PyT8/kdS+4x75Wvqjh3o0HofCpgqCva5yM4kxvx9U8g== X-MS-TrafficTypeDiagnostic: MWHPR03MB2766: X-Microsoft-Exchange-Diagnostics: 1; MWHPR03MB2766; 31:b0i1QL4N2wieE/DJfaVCBt0mKDQ2D6xzkPHyi5VrjTgCGdKlf8JbTd5Ad2VOs0PdI0Jp9c1a7bXmiJC5mC7MzcbP9kqDaQVB/2mo+1QrWcN64qvVccfMjz3trtQvdwqHi1N2d0A33YlTjfIXiKKNMhWMic3sXPCQojvw93SmkfncMY0vV5YwCD09GaS6m2d5hM/hVtV57EncyKO7BvdMvtrxN2puoOZC9duy8ZXJyqE=; 4:7aVcl4bJqsbCZm2aIIfdWJR4TRZ5CVR6tEHtQTZWL5WH8J9Ixa7v36uzbYEk+XZdMiDX/XW64uT+OwYXa0+vtAQogWiQVwD1iK62iQFKSbRSXD3y6QsKeDZ20L+krf9VhRVV+nQ9/EmT/taJw4+3Hyj7jAdnNM8SQ73cfR2JFXcSWlGnAJL6wHiUuKRi+cy7/3mTxpbWra0BrhFZsDL/vUOzrZOxna3eiBiCT5dS5qxWqGcfvv3AlkNpkYII6t8yBPbrBrs3vHzbm9uC9a0HMrsjQuKdbEkV/52ek/EfEgGF1vi7ToCGDNPXFzQhlkV9 X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(185117386973197); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6095135)(2401047)(8121501046)(5005006)(93006095)(93001095)(3002001)(3231221)(944501244)(52105095)(10201501046)(6055026)(6096035)(20161123561025)(201703131430075)(201703131448075)(201703131433075)(201703151042153)(20161123565025)(20161123563025)(20161123559100)(20161123556025)(201708071742011); SRVR:MWHPR03MB2766; BCL:0; PCL:0; RULEID:(400006); SRVR:MWHPR03MB2766; X-Forefront-PRVS: 06167FAD59 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; MWHPR03MB2766; 23:XKTRelRXXsZyFm4gS5LQaSrI2aK2UFjYTE3frZU3R?= =?us-ascii?Q?59MHhBRHHUx0Ck4eW7YQSsUY5dczbYSUNU1kRQxNOeuwtCf6z+PmhRdFMRl+?= =?us-ascii?Q?8puIlFPTnr1WIFW4NgrExtNuWn/DQ0bYw5Nb+QC4SaqkMKKs5Ma3+Hlmp58l?= =?us-ascii?Q?/cAkd2Qr3Bhm2aApT6hTA37jGwp6uJx00hjIfbNLllcT+5fRGKWjY2R0lVg+?= =?us-ascii?Q?SY+Mvhel6cz/bmlTIvMoPkLwoNxL/rTcti8mbh4JuGkrLzghN5dNSlyJvyVB?= =?us-ascii?Q?RvW8ry4+hnTELTamc9Ifduf8VTGk0/F0IpHj8YPbR12JMr/k+sfBWzAdWLq/?= =?us-ascii?Q?4EEdfw24MZkpdsg/3hOED0l5BhjSfa0DYWesaQj9ucooTZGnAP5nK161TENR?= =?us-ascii?Q?X4Jl4i01kbgZMPTWkMtGxPpQkeTXlPF8YYHYFTumlWMsEcEeuj+0NpWid9mU?= =?us-ascii?Q?ze+V9h8MPOyLcCG+6GoBUqWB0ZwLkrnXqE1+iXNhlIPQ4CIzpmrLOu/aIKub?= =?us-ascii?Q?AjMAB8hlml1hhba40tlEBimfssyWSSfcHsHWhMbPsIByZJQ2lH3Yb/FinRyl?= =?us-ascii?Q?6LM5wUC+9DGmUAtOrzLcYOAo8mZC9cf6BCeNmg8gF9YaXP9Y65j4iAg3Kt2a?= =?us-ascii?Q?v+9H2NzC9u8Ox1OuvUhs+NPwbtO8sfV6YAxwxBgZNqUGAWbjgOf5VJhM8FxT?= =?us-ascii?Q?hDwLsGZ+QtJSSnNC0+wdD/cf3St1h8ans7xUQbeBIJOgoZbhv1ljWdSthJeM?= =?us-ascii?Q?fxywWxHtwVNaQ6xceNPagMbimKiScAI60WtK+aZjNniiW87ewCFXDte+9r8o?= =?us-ascii?Q?6VhZveuLFxFWA1qTB1T4wEOGzWoB7evXDdX8v854HvtnVaSuf4QadxmN/Tam?= =?us-ascii?Q?e+p8y630I4DtOiOYBYBH/T+at42u9A2BG+Zf6YjueVZar/ePvu0UzVEX5m+Z?= =?us-ascii?Q?wrEQ6y3B9wGtFr/40C/M3zbpyVRarHeZBjvzwcAC9Uv4IPH56F/ZRtv5Xz2E?= =?us-ascii?Q?6JWihs1Op6mG2smff/si/4PIM+W8cd7W8pV7fxFQYhtUuTq4/B4JJZ+aEZZO?= =?us-ascii?Q?iSibJxfBWitVOreyujqJU7aF08ZXo4BAjJq25awumeF7tGVFtxZqyB75bx0m?= =?us-ascii?Q?lwsfPFFVgsmHD6FGlXKTmiCpfQBaNbUmt89/soz1jVmE1nZc5fGuA=3D=3D?= X-Microsoft-Antispam-Message-Info: mCo3WM4XHtgIv8t6ITaYgZHLfyEGgNB+ViphxhVj4I1dEp45WMAH0MVPy1Av+9knSlFzZwFvLARrKWsonCzXaWDcNrTUkLJ6r0xRjY/in+NYNy2Cljf0irkKEpOF7PNn8Rf3W6uuSxtsJ9FvFkpdJA9n0jLRAZmSGYT1hdjdFnUYF+WFGYZJYFEGhXsL2v3i X-Microsoft-Exchange-Diagnostics: 1; MWHPR03MB2766; 6:QWsn6spsvcAWXcY7tCPXbtY+CIErGgpIrlCnFNTSP7QFm3B9OKXynT4QcruG52ipNUStOdJg58COWskq183oaNB6y4ebWLcQRuUeN0bfM/sXBYZEhW0gym09ftS/CGdYh5naYZD+Kn+hCm7D3Ky271dt43YrdXC3niVIPzMSfrO2vWjWmQe6xqIR5brlqeZRx79OCe9jCeriZxkjtaZjbmRA/oa9DNX5/CM+X+1uGYLbT8WnIh8+VG47xMjXo+8X+Aohfla0TVmqJ4gkAV0tQHhGI4yPNfnKcJm4OLQPlPt6GdW/ufX8Fn8qNFa91gBNJKQFB/oCTga1o9Sq7oqYp1AaI75stf3qgdVd1Jc92i0=; 5:0NipIDl5lstZou3iSOKkfqsuIR4h0KODBgYmXV1ZuQn9Qz2g1hIeCvqi8MOx/FapG6P5iPpvROu7W82OzI2bue5Nb6tjbLhKSsorzQDVrwM+NwNKgDt8tWvGFSmcwsVuL5vg1AkG7LfxSrnYgSdO/qhXDgzWAAgZekPWRx61x28=; 24:CbA+YELpbtgjlS2oCyqlZs2mahu352WhG50zrIpuQBt+QbSMM8mHfqubtJWNY4T3YwxwyxlEt1dxfgcLHQCa7XlTJ7GH6pZGs1J3gm4Hv/o=; 7:7s1kopdNadhOeNyzkjJdrDOTUlFhjDZjcQuM2UPVzaiJsAfxRoUETSyTcHLzkDySR4Kq8v/S21mtFUo81wfC43P6RFPbvLG3ZBNx8CQPWBezpSbo//JXoUWMQkbIf1IjQ0uAhKvbAWgPeQNLAwOS8MYxJgVBG1wuXJ1NpAbmcrvAgUrbetfdjtM7Wlk0/nrTwsd9aUe2ozIwWSNiiuFqTxpjxih3rIETsUZFIrjZRKNgfFWbGnex9F1H9SPMqEbu SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Mar 2018 14:55:43.3813 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 8c511b30-f5e2-40f3-0200-08d58da97d67 X-MS-Exchange-CrossTenant-Id: 5afe0b00-7697-4969-b663-5eab37d5f47e X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=5afe0b00-7697-4969-b663-5eab37d5f47e; Ip=[192.88.168.50]; Helo=[tx30smr01.am.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: MWHPR03MB2766 Subject: [dpdk-dev] [PATCH] examples/l3fwd: adding event queue support X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Mar 2018 14:55:47 -0000 This patch set to add the support for eventdev based queue mode support to the l3fwd application. 1. Eventdev support with parallel queue 2. Eventdev support with atomic queue This patch adds - New command line parameter is added named as "dequeue-mode" which identifies dequeue method i.e. dequeue via eventdev or polling (default is polling) . If dequeue mode is via: a. eventdev: New parameters are added -e, -a, -l to cater eventdev config, adapter config and link configuration respectively. "--config" option will be invalid in this case. b. poll mode: It will work as of existing way and option for eventdev parameters(-e, -a, -l) will be invalid. - Functions are added in l3fwd_em.c and l3fwd_lpm.c for packet I/O operation The main purpose of this RFC is get comments on the approach. This is a *not tested* code. Signed-off-by: Sunil Kumar Kori --- examples/l3fwd/Makefile | 2 +- examples/l3fwd/l3fwd.h | 21 ++ examples/l3fwd/l3fwd_em.c | 100 ++++++++ examples/l3fwd/l3fwd_eventdev.c | 541 ++++++++++++++++++++++++++++++++++++++++ examples/l3fwd/l3fwd_eventdev.h | 85 +++++++ examples/l3fwd/l3fwd_lpm.c | 100 ++++++++ examples/l3fwd/main.c | 318 +++++++++++++++++++---- examples/l3fwd/meson.build | 2 +- 8 files changed, 1120 insertions(+), 49 deletions(-) create mode 100644 examples/l3fwd/l3fwd_eventdev.c create mode 100644 examples/l3fwd/l3fwd_eventdev.h diff --git a/examples/l3fwd/Makefile b/examples/l3fwd/Makefile index cccdd9d..94ba537 100644 --- a/examples/l3fwd/Makefile +++ b/examples/l3fwd/Makefile @@ -5,7 +5,7 @@ APP = l3fwd # all source are stored in SRCS-y -SRCS-y := main.c l3fwd_lpm.c l3fwd_em.c +SRCS-y := main.c l3fwd_lpm.c l3fwd_em.c l3fwd_eventdev.c # Build using pkg-config variables if possible $(shell pkg-config --exists libdpdk) diff --git a/examples/l3fwd/l3fwd.h b/examples/l3fwd/l3fwd.h index c962dea..675abd1 100644 --- a/examples/l3fwd/l3fwd.h +++ b/examples/l3fwd/l3fwd.h @@ -69,6 +69,17 @@ struct lcore_conf { void *ipv6_lookup_struct; } __rte_cache_aligned; +struct l3fwd_lkp_mode { + void (*setup)(int); + int (*check_ptype)(int); + rte_rx_callback_fn cb_parse_ptype; + int (*main_loop)(void *); + void* (*get_ipv4_lookup_struct)(int); + void* (*get_ipv6_lookup_struct)(int); +}; + +extern struct l3fwd_lkp_mode l3fwd_lkp; + extern volatile bool force_quit; /* ethernet addresses of ports */ @@ -81,11 +92,16 @@ extern uint32_t enabled_port_mask; /* Used only in exact match mode. */ extern int ipv6; /**< ipv6 is false by default. */ extern uint32_t hash_entry_number; +extern int promiscuous_on; +extern int numa_on; /**< NUMA is enabled by default. */ +extern uint16_t nb_rxd; extern xmm_t val_eth[RTE_MAX_ETHPORTS]; extern struct lcore_conf lcore_conf[RTE_MAX_LCORE]; +extern struct rte_mempool *pktmbuf_pool[]; + /* Send burst of packets on an output interface */ static inline int send_burst(struct lcore_conf *qconf, uint16_t n, uint16_t port) @@ -208,5 +224,10 @@ lpm_get_ipv4_l3fwd_lookup_struct(const int socketid); void * lpm_get_ipv6_l3fwd_lookup_struct(const int socketid); +int +prepare_ptype_parser(uint16_t portid, uint16_t queueid); + +void +check_all_ports_link_status(uint16_t port_num, uint32_t port_mask); #endif /* __L3_FWD_H__ */ diff --git a/examples/l3fwd/l3fwd_em.c b/examples/l3fwd/l3fwd_em.c index 9dc3b8c..199ff75 100644 --- a/examples/l3fwd/l3fwd_em.c +++ b/examples/l3fwd/l3fwd_em.c @@ -21,12 +21,14 @@ #include #include #include +#include #include #include #include #include #include "l3fwd.h" +#include "l3fwd_eventdev.h" #if defined(RTE_ARCH_X86) || defined(RTE_MACHINE_CPUFLAG_CRC32) #define EM_HASH_CRC 1 @@ -612,6 +614,101 @@ em_cb_parse_ptype(uint16_t port __rte_unused, uint16_t queue __rte_unused, return nb_pkts; } +/* main EM processing loop for eventdev*/ +int +em_eventdev_main_loop(__attribute__((unused)) void *dummy) +{ + struct rte_event ev[MAX_PKT_BURST]; + struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; + struct rte_event_port_conf event_port_conf; + unsigned int lcore_id; + uint64_t prev_tsc, diff_tsc, cur_tsc; + int i, nb_rx; + uint8_t queueid; + uint16_t portid, dequeue_len; + uint8_t event_port_id = INVALID_EVENDEV_ID; + struct lcore_conf *qconf; + const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / + US_PER_S * BURST_TX_DRAIN_US; + + prev_tsc = 0; + + lcore_id = rte_lcore_id(); + qconf = &lcore_conf[lcore_id]; + + if (qconf->n_rx_queue == 0) { + RTE_LOG(INFO, L3FWD, "lcore %u has nothing to do\n", lcore_id); + return 0; + } + + RTE_LOG(INFO, L3FWD, "entering main loop on lcore %u\n", lcore_id); + + for (i = 0; i < qconf->n_rx_queue; i++) { + + portid = qconf->rx_queue_list[i].port_id; + queueid = qconf->rx_queue_list[i].queue_id; + RTE_LOG(INFO, L3FWD, + " -- lcoreid=%u portid=%u rxqueueid=%hhu\n", + lcore_id, portid, queueid); + } + + for (i = 0; i < link_config.nb_links; i++) { + if (link_config.links[i].lcore_id == lcore_id) + event_port_id = link_config.links[i].event_portid; + } + + rte_event_port_default_conf_get(event_devices[0].dev_id, event_port_id, + &event_port_conf); + dequeue_len = event_port_conf.dequeue_depth; + + while (!force_quit) { + + cur_tsc = rte_rdtsc(); + + /* + * TX burst queue drain + */ + diff_tsc = cur_tsc - prev_tsc; + if (unlikely(diff_tsc > drain_tsc)) { + + for (i = 0; i < qconf->n_tx_port; ++i) { + portid = qconf->tx_port_id[i]; + if (qconf->tx_mbufs[portid].len == 0) + continue; + send_burst(qconf, + qconf->tx_mbufs[portid].len, + portid); + qconf->tx_mbufs[portid].len = 0; + } + + prev_tsc = cur_tsc; + } + + /* + * Read packet from event ports + */ + + nb_rx = rte_event_dequeue_burst(event_devices[0].dev_id, + event_port_id, + ev, dequeue_len, 0); + if (nb_rx == 0) + continue; + + for (i = 0; i < nb_rx; ++i) { + pkts_burst[0] = ev[i].mbuf; + portid = ev[i].flow_id; +#if defined RTE_ARCH_X86 || defined RTE_MACHINE_CPUFLAG_NEON + l3fwd_em_send_packets(1, pkts_burst, portid, qconf); +#else + l3fwd_em_no_opt_send_packets(1, pkts_burst, + portid, qconf); +#endif + } + } + + return 0; +} + /* main processing loop */ int em_main_loop(__attribute__((unused)) void *dummy) @@ -631,6 +728,9 @@ em_main_loop(__attribute__((unused)) void *dummy) lcore_id = rte_lcore_id(); qconf = &lcore_conf[lcore_id]; + if (lcore_dequeue_mode[lcore_id] == EVENTDEV_DEQUEUE) + return em_eventdev_main_loop(dummy); + if (qconf->n_rx_queue == 0) { RTE_LOG(INFO, L3FWD, "lcore %u has nothing to do\n", lcore_id); return 0; diff --git a/examples/l3fwd/l3fwd_eventdev.c b/examples/l3fwd/l3fwd_eventdev.c new file mode 100644 index 0000000..f7d9b4c --- /dev/null +++ b/examples/l3fwd/l3fwd_eventdev.c @@ -0,0 +1,541 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2018 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "l3fwd.h" +#include "l3fwd_eventdev.h" + + +static struct eventdev_params eventdev_config[RTE_MAX_EVENTDEV_COUNT]; +static uint16_t nb_eventdev_params; +struct eventdev_info *event_devices; +static struct adapter_params rx_adapter_config; +struct link_params link_config; +enum dequeue_mode lcore_dequeue_mode[RTE_MAX_LCORE]; + + + +int +parse_eventdev_config(const char *evq_arg) +{ + char s[256]; + const char *p, *p0 = evq_arg; + char *end; + enum fieldnames { + FLD_EVENTDEV_ID = 0, + FLD_EVENT_QUEUE, + FLD_EVENT_PORT, + FLD_COUNT + }; + unsigned long int_fld[FLD_COUNT]; + char *str_fld[FLD_COUNT]; + int i; + unsigned int size; + + /*First set all eventdev_config to default*/ + for (i = 0; i < RTE_MAX_EVENTDEV_COUNT; i++) { + eventdev_config[i].num_eventqueue = 1; + eventdev_config[i].num_eventport = RTE_MAX_LCORE; + } + + nb_eventdev_params = 0; + + while ((p = strchr(p0, '(')) != NULL) { + ++p; + if ((p0 = strchr(p, ')')) == NULL) + return -1; + + size = p0 - p; + if (size >= sizeof(s)) + return -1; + + snprintf(s, sizeof(s), "%.*s", size, p); + if (rte_strsplit(s, sizeof(s), str_fld, FLD_COUNT, ',') != + FLD_COUNT) + return -1; + + for (i = 0; i < FLD_COUNT; i++) { + errno = 0; + int_fld[i] = strtoul(str_fld[i], &end, 0); + if (errno != 0 || end == str_fld[i] || int_fld[i] > 255) + return -1; + } + + if (nb_eventdev_params >= RTE_MAX_EVENTDEV_COUNT) { + printf("exceeded max number of eventdev params: %hu\n", + nb_eventdev_params); + return -1; + } + + eventdev_config[nb_eventdev_params].num_eventqueue = + (uint8_t)int_fld[FLD_EVENT_QUEUE]; + eventdev_config[nb_eventdev_params].num_eventport = + (uint8_t)int_fld[FLD_EVENT_PORT]; + eventdev_config[nb_eventdev_params].eventdev_id = + (uint8_t)int_fld[FLD_EVENTDEV_ID]; + ++nb_eventdev_params; + } + + return 0; +} + +int +parse_adapter_config(const char *evq_arg) +{ + char s[256]; + const char *p, *p0 = evq_arg; + char *end; + enum fieldnames { + FLD_ETHDEV_ID = 0, + FLD_ETHDEV_QID, + FLD_EVENT_QID_MODE, + FLD_EVENTQ_ID, + FLD_EVENT_PRIO, + FLD_EVENT_DEVID, + FLD_COUNT + }; + unsigned long int_fld[FLD_COUNT]; + char *str_fld[FLD_COUNT]; + int i, index = 0, j = 0; + unsigned int size; + + index = rx_adapter_config.nb_rx_adapter; + + while ((p = strchr(p0, '(')) != NULL) { + j = rx_adapter_config.config[index].nb_connections; + ++p; + if ((p0 = strchr(p, ')')) == NULL) + return -1; + + size = p0 - p; + if (size >= sizeof(s)) + return -1; + + snprintf(s, sizeof(s), "%.*s", size, p); + if (rte_strsplit(s, sizeof(s), str_fld, FLD_COUNT, ',') != + FLD_COUNT) + return -1; + + for (i = 0; i < FLD_COUNT; i++) { + errno = 0; + int_fld[i] = strtoul(str_fld[i], &end, 0); + if (errno != 0 || end == str_fld[i] || int_fld[i] > 255) + return -1; + } + + if (index >= RTE_MAX_EVENTDEV_COUNT) { + printf("exceeded max number of eventdev params: %hu\n", + rx_adapter_config.nb_rx_adapter); + return -1; + } + + rx_adapter_config.config[index].connections[j].ethdev_id = + (uint8_t)int_fld[FLD_ETHDEV_ID]; + rx_adapter_config.config[index].connections[j].ethdev_rx_qid = + (uint8_t)int_fld[FLD_ETHDEV_QID]; + rx_adapter_config.config[index].connections[j].ethdev_rx_qid_mode = + (uint8_t)int_fld[FLD_EVENT_QID_MODE]; + rx_adapter_config.config[index].connections[j].eventq_id = + (uint8_t)int_fld[FLD_EVENTQ_ID]; + rx_adapter_config.config[index].connections[j].event_prio = + (uint8_t)int_fld[FLD_EVENT_PRIO]; + rx_adapter_config.config[index].connections[j].eventdev_id = + (uint8_t)int_fld[FLD_EVENT_DEVID]; + rx_adapter_config.config[index].nb_connections++; + } + + rx_adapter_config.nb_rx_adapter++; + return 0; +} + +int +parse_link_config(const char *evq_arg) +{ + char s[256]; + const char *p, *p0 = evq_arg; + char *end; + enum fieldnames { + FLD_EVENT_PORTID = 0, + FLD_EVENT_QID, + FLD_EVENT_DEVID, + FLD_LCORE_ID, + FLD_COUNT + }; + unsigned long int_fld[FLD_COUNT]; + char *str_fld[FLD_COUNT]; + int i, index = 0; + unsigned int size; + + /*First set all adapter_config to default*/ + memset(&link_config, 0, sizeof(struct link_params)); + while ((p = strchr(p0, '(')) != NULL) { + index = link_config.nb_links; + ++p; + if ((p0 = strchr(p, ')')) == NULL) + return -1; + + size = p0 - p; + if (size >= sizeof(s)) + return -1; + + snprintf(s, sizeof(s), "%.*s", size, p); + if (rte_strsplit(s, sizeof(s), str_fld, FLD_COUNT, ',') != + FLD_COUNT) + return -1; + + for (i = 0; i < FLD_COUNT; i++) { + errno = 0; + int_fld[i] = strtoul(str_fld[i], &end, 0); + if (errno != 0 || end == str_fld[i] || int_fld[i] > 255) + return -1; + } + + if (index >= RTE_MAX_EVENTDEV_COUNT) { + printf("exceeded max number of eventdev params: %hu\n", + link_config.nb_links); + return -1; + } + + link_config.links[index].event_portid = + (uint8_t)int_fld[FLD_EVENT_PORTID]; + link_config.links[index].eventq_id = + (uint8_t)int_fld[FLD_EVENT_QID]; + link_config.links[index].eventdev_id = + (uint8_t)int_fld[FLD_EVENT_DEVID]; + link_config.links[index].lcore_id = + (uint8_t)int_fld[FLD_LCORE_ID]; + lcore_dequeue_mode[link_config.links[index].lcore_id] = + EVENTDEV_DEQUEUE; + link_config.nb_links++; + } + + return 0; +} + +static int +eventdev_configure(void) +{ + int ret = -1; + uint8_t i, j; + void *ports, *queues; + struct rte_event_dev_config eventdev_conf = {0}; + struct rte_event_dev_info eventdev_def_conf = {0}; + struct rte_event_queue_conf eventq_conf = {0}; + struct rte_event_port_conf port_conf = {0}; + struct rte_event_eth_rx_adapter_queue_conf queue_conf = {0}; + + /*First allocate space for event device information*/ + event_devices = rte_zmalloc("event-dev", + sizeof(struct eventdev_info) * nb_eventdev_params, 0); + if (event_devices == NULL) { + printf("Error in allocating memory for event devices\n"); + return ret; + } + + for (i = 0; i < nb_eventdev_params; i++) { + /*Now allocate space for event ports request from user*/ + ports = rte_zmalloc("event-ports", + sizeof(uint8_t) * eventdev_config[i].num_eventport, 0); + if (ports == NULL) { + printf("Error in allocating memory for event ports\n"); + rte_free(event_devices); + return ret; + } + + event_devices[i].port = ports; + + /*Now allocate space for event queues request from user*/ + queues = rte_zmalloc("event-queues", + sizeof(uint8_t) * eventdev_config[i].num_eventqueue, 0); + if (queues == NULL) { + printf("Error in allocating memory for event queues\n"); + rte_free(event_devices[i].port); + rte_free(event_devices); + return ret; + } + + event_devices[i].queue = queues; + event_devices[i].dev_id = eventdev_config[i].eventdev_id; + + /* get default values of eventdev*/ + memset(&eventdev_def_conf, 0, + sizeof(struct rte_event_dev_info)); + ret = rte_event_dev_info_get(event_devices[i].dev_id, + &eventdev_def_conf); + if (ret < 0) { + printf("Error in getting event device info, devid: %d\n", + event_devices[i].dev_id); + return ret; + } + + memset(&eventdev_conf, 0, sizeof(struct rte_event_dev_config)); + eventdev_conf.nb_events_limit = -1; + eventdev_conf.nb_event_queues = + eventdev_config[i].num_eventqueue; + eventdev_conf.nb_event_ports = + eventdev_config[i].num_eventport; + eventdev_conf.nb_event_queue_flows = + eventdev_def_conf.max_event_queue_flows; + eventdev_conf.nb_event_port_dequeue_depth = + eventdev_def_conf.max_event_port_dequeue_depth; + eventdev_conf.nb_event_port_enqueue_depth = + eventdev_def_conf.max_event_port_enqueue_depth; + + ret = rte_event_dev_configure(event_devices[i].dev_id, + &eventdev_conf); + if (ret < 0) { + printf("Error in configuring event device\n"); + return ret; + } + + memset(&eventq_conf, 0, sizeof(struct rte_event_queue_conf)); + eventq_conf.nb_atomic_flows = 1; + eventq_conf.schedule_type = RTE_SCHED_TYPE_ATOMIC; + for (j = 0; j < eventdev_config[i].num_eventqueue; j++) { + ret = rte_event_queue_setup(event_devices[i].dev_id, j, + &eventq_conf); + if (ret < 0) { + printf("Error in event queue setup\n"); + return ret; + } + event_devices[i].queue[j] = j; + } + + for (j = 0; j < eventdev_config[i].num_eventport; j++) { + ret = rte_event_port_setup(event_devices[i].dev_id, j, NULL); + if (ret < 0) { + printf("Error in event port setup\n"); + return ret; + } + event_devices[i].port[j] = j; + } + } + + for (i = 0; i < rx_adapter_config.nb_rx_adapter; i++) { + for (j = 0; j < rx_adapter_config.config[i].nb_connections; j++) { + ret = rte_event_eth_rx_adapter_create(j, + rx_adapter_config.config[i].connections[j].eventdev_id, + &port_conf); + if (ret < 0) { + printf("Error in event eth adapter creation\n"); + return ret; + } + rx_adapter_config.config[i].connections[j].adapter_id = + j; + } + } + + for (j = 0; j < link_config.nb_links; j++) { + ret = rte_event_port_link(link_config.links[j].eventdev_id, + link_config.links[j].event_portid, + &link_config.links[j].eventq_id, NULL, 1); + if (ret < 0) { + printf("Error in event port linking\n"); + return ret; + } + } + + queue_conf.rx_queue_flags = + RTE_EVENT_ETH_RX_ADAPTER_QUEUE_FLOW_ID_VALID; + + for (i = 0; i < rx_adapter_config.nb_rx_adapter; i++) { + for (j = 0; j < rx_adapter_config.config[i].nb_connections; j++) { + queue_conf.ev.queue_id = + rx_adapter_config.config[i].connections[j].eventq_id; + queue_conf.ev.priority = + rx_adapter_config.config[i].connections[j].event_prio; + queue_conf.ev.flow_id = + rx_adapter_config.config[i].connections[j].ethdev_id; + queue_conf.ev.sched_type = + rx_adapter_config.config[i].connections[j].ethdev_rx_qid_mode; + ret = rte_event_eth_rx_adapter_queue_add( + rx_adapter_config.config[i].connections[j].adapter_id, + rx_adapter_config.config[i].connections[j].ethdev_id, + rx_adapter_config.config[i].connections[j].ethdev_rx_qid, + &queue_conf); + if (ret < 0) { + printf("Error in adding eth queue in event adapter\n"); + return ret; + } + } + } + + for (i = 0; i < nb_eventdev_params; i++) { + ret = rte_event_dev_start(event_devices[i].dev_id); + if (ret < 0) { + printf("Error in starting event device, devid: %d\n", + event_devices[i].dev_id); + return ret; + } + } + + return 0; +} + + +int +config_eventdev(void) +{ + struct lcore_conf *qconf; + struct rte_eth_dev_info dev_info; + int i, j, ret; + unsigned nb_ports; + uint16_t queueid, portid; + unsigned lcore_id; + uint8_t queue, socketid; + + nb_ports = rte_eth_dev_count(); + + /* Rx queue configuration is to be done */ + for (i = 0; i < rx_adapter_config.nb_rx_adapter; i++) { + printf("\nInitializing rx queues on lcore %u ... ", lcore_id); + fflush(stdout); + /* init RX queues */ + for (j = 0; j < rx_adapter_config.config[i].nb_connections; j++) { + struct rte_eth_dev *dev; + struct rte_eth_conf *conf; + struct rte_eth_rxconf rxq_conf; + + portid = rx_adapter_config.config[i].connections[j].ethdev_id; + queueid = rx_adapter_config.config[i].connections[j].ethdev_rx_qid; + dev = &rte_eth_devices[portid]; + conf = &dev->data->dev_conf; + + if (numa_on) + socketid = + (uint8_t)rte_lcore_to_socket_id(lcore_id); + else + socketid = 0; + + printf("rxq=%d,%d,%d ", portid, queueid, socketid); + fflush(stdout); + + rte_eth_dev_info_get(portid, &dev_info); + rxq_conf = dev_info.default_rxconf; + rxq_conf.offloads = conf->rxmode.offloads; + ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd, + socketid, + &rxq_conf, + pktmbuf_pool[socketid]); + if (ret < 0) + rte_exit(EXIT_FAILURE, + "rte_eth_rx_queue_setup: err=%d, port=%d\n", + ret, portid); + } + } + + printf("\n"); + + ret = eventdev_configure(); + if (ret < 0) + rte_exit(EXIT_FAILURE, + "event dev configure: err=%d\n", ret); + + /* start ports */ + for (portid = 0; portid < nb_ports; portid++) { + if ((enabled_port_mask & (1 << portid)) == 0) { + continue; + } + /* Start device */ + ret = rte_eth_dev_start(portid); + if (ret < 0) + rte_exit(EXIT_FAILURE, + "rte_eth_dev_start: err=%d, port=%d\n", + ret, portid); + + /* + * If enabled, put device in promiscuous mode. + * This allows IO forwarding mode to forward packets + * to itself through 2 cross-connected ports of the + * target machine. + */ + if (promiscuous_on) + rte_eth_promiscuous_enable(portid); + } + + printf("\n"); + + for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { + if (rte_lcore_is_enabled(lcore_id) == 0) + continue; + qconf = &lcore_conf[lcore_id]; + for (queue = 0; queue < qconf->n_rx_queue; ++queue) { + portid = qconf->rx_queue_list[queue].port_id; + queueid = qconf->rx_queue_list[queue].queue_id; + if (prepare_ptype_parser(portid, queueid) == 0) + rte_exit(EXIT_FAILURE, "ptype check fails\n"); + } + } + + + check_all_ports_link_status(nb_ports, enabled_port_mask); + + ret = 0; + /* launch per-lcore init on every lcore */ + rte_eal_mp_remote_launch(l3fwd_lkp.main_loop, NULL, CALL_MASTER); + RTE_LCORE_FOREACH_SLAVE(lcore_id) { + if (rte_eal_wait_lcore(lcore_id) < 0) { + ret = -1; + break; + } + } + + /* stop ports */ + for (portid = 0; portid < nb_ports; portid++) { + if ((enabled_port_mask & (1 << portid)) == 0) + continue; + printf("Closing port %d...", portid); + rte_eth_dev_stop(portid); + rte_eth_dev_close(portid); + printf(" Done\n"); + } + printf("Bye...\n"); + + return ret; +} diff --git a/examples/l3fwd/l3fwd_eventdev.h b/examples/l3fwd/l3fwd_eventdev.h new file mode 100644 index 0000000..6a778b0 --- /dev/null +++ b/examples/l3fwd/l3fwd_eventdev.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2018 NXP + */ + +#ifndef __L3_FWD_EVENTDEV_H__ +#define __L3_FWD_EVENTDEV_H__ + +#define INVALID_EVENDEV_ID 0xFF + +#define RTE_MAX_EVENTDEV_COUNT RTE_MAX_LCORE + +/* + * Default RX Dequeue size + */ +#define MAX_EVENTDEV_PKT_BURST 8 + +struct eventdev_params { + uint8_t num_eventqueue; + uint8_t num_eventport; + uint8_t eventdev_id; +}; + +struct connection_info { + uint8_t ethdev_id; + uint8_t eventq_id; + uint8_t event_prio; + uint8_t ethdev_rx_qid; + int32_t ethdev_rx_qid_mode; + int32_t eventdev_id; + int32_t adapter_id; +}; + +struct adapter_config { + struct connection_info connections[RTE_MAX_EVENTDEV_COUNT]; + uint8_t nb_connections; +}; + +struct adapter_params { + struct adapter_config config[RTE_MAX_EVENTDEV_COUNT]; + uint8_t nb_rx_adapter; +}; + +struct eventdev_info { + uint8_t dev_id; + uint8_t *port; + uint8_t *queue; +}; + +struct link_info { + uint8_t event_portid; + uint8_t eventq_id; + uint8_t eventdev_id; + uint8_t lcore_id; +}; +struct link_params { + struct link_info links[RTE_MAX_EVENTDEV_COUNT]; + uint8_t nb_links; +}; + +enum dequeue_mode { + POLL_DEQUEUE = 0, + EVENTDEV_DEQUEUE, +}; + +extern struct link_params link_config; +extern struct eventdev_info *event_devices; +extern enum dequeue_mode lcore_dequeue_mode[RTE_MAX_LCORE]; + +int +em_eventdev_main_loop(__attribute__((unused)) void *dummy); + +int +lpm_eventdev_main_loop(__attribute__((unused)) void *dummy); + +int +parse_eventdev_config(const char *evq_arg); +int +parse_adapter_config(const char *evq_arg); +int +parse_link_config(const char *evq_arg); + +int +config_eventdev(void); + +#endif /* __L3_FWD_EVENTDEV_H__ */ diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c index a747126..b2a3c1d 100644 --- a/examples/l3fwd/l3fwd_lpm.c +++ b/examples/l3fwd/l3fwd_lpm.c @@ -25,8 +25,10 @@ #include #include #include +#include #include "l3fwd.h" +#include "l3fwd_eventdev.h" struct ipv4_l3fwd_lpm_route { uint32_t ip; @@ -168,6 +170,101 @@ lpm_get_dst_port_with_ipv4(const struct lcore_conf *qconf, struct rte_mbuf *pkt, #include "l3fwd_lpm.h" #endif +/* main LPM processing loop for eventdev*/ +int +lpm_eventdev_main_loop(__attribute__((unused)) void *dummy) +{ + struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; + struct rte_event ev[MAX_PKT_BURST]; + struct rte_event_port_conf event_port_conf; + unsigned int lcore_id; + uint64_t prev_tsc, diff_tsc, cur_tsc; + int i, nb_rx; + uint16_t portid, dequeue_len; + uint8_t event_port_id = INVALID_EVENDEV_ID; + uint8_t queueid; + struct lcore_conf *qconf; + const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / + US_PER_S * BURST_TX_DRAIN_US; + + prev_tsc = 0; + + lcore_id = rte_lcore_id(); + qconf = &lcore_conf[lcore_id]; + + if (qconf->n_rx_queue == 0) { + RTE_LOG(INFO, L3FWD, "lcore %u has nothing to do\n", lcore_id); + return 0; + } + + RTE_LOG(INFO, L3FWD, "entering main loop on lcore %u\n", lcore_id); + + for (i = 0; i < qconf->n_rx_queue; i++) { + + portid = qconf->rx_queue_list[i].port_id; + queueid = qconf->rx_queue_list[i].queue_id; + RTE_LOG(INFO, L3FWD, + " -- lcoreid=%u portid=%u rxqueueid=%hhu\n", + lcore_id, portid, queueid); + } + + for (i = 0; i < link_config.nb_links; i++) { + if (link_config.links[i].lcore_id == lcore_id) + event_port_id = link_config.links[i].event_portid; + } + + rte_event_port_default_conf_get(event_devices[0].dev_id, event_port_id, + &event_port_conf); + dequeue_len = event_port_conf.dequeue_depth; + + while (!force_quit) { + + cur_tsc = rte_rdtsc(); + + /* + * TX burst queue drain + */ + diff_tsc = cur_tsc - prev_tsc; + if (unlikely(diff_tsc > drain_tsc)) { + + for (i = 0; i < qconf->n_tx_port; ++i) { + portid = qconf->tx_port_id[i]; + if (qconf->tx_mbufs[portid].len == 0) + continue; + send_burst(qconf, + qconf->tx_mbufs[portid].len, + portid); + qconf->tx_mbufs[portid].len = 0; + } + + prev_tsc = cur_tsc; + } + + /* + * Read packet from event ports + */ + nb_rx = rte_event_dequeue_burst(event_devices[0].dev_id, + event_port_id, + ev, dequeue_len, 0); + if (nb_rx == 0) + continue; + + for (i = 0; i < nb_rx; i++) { + pkts_burst[0] = ev[i].mbuf; + portid = ev[i].flow_id; +#if defined RTE_ARCH_X86 || defined RTE_MACHINE_CPUFLAG_NEON \ + || defined RTE_ARCH_PPC_64 + l3fwd_lpm_send_packets(1, pkts_burst, portid, qconf); +#else + l3fwd_lpm_no_opt_send_packets(1, pkts_burst, + portid, qconf); +#endif /* X86 */ + } + } + + return 0; +} + /* main processing loop */ int lpm_main_loop(__attribute__((unused)) void *dummy) @@ -187,6 +284,9 @@ lpm_main_loop(__attribute__((unused)) void *dummy) lcore_id = rte_lcore_id(); qconf = &lcore_conf[lcore_id]; + if (lcore_dequeue_mode[lcore_id] == EVENTDEV_DEQUEUE) + return lpm_eventdev_main_loop(dummy); + if (qconf->n_rx_queue == 0) { RTE_LOG(INFO, L3FWD, "lcore %u has nothing to do\n", lcore_id); return 0; diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c index e7111fa..eff1ac5 100644 --- a/examples/l3fwd/main.c +++ b/examples/l3fwd/main.c @@ -46,6 +46,7 @@ #include #include "l3fwd.h" +#include "l3fwd_eventdev.h" /* * Configurable number of RX/TX ring descriptors @@ -59,17 +60,17 @@ #define MAX_LCORE_PARAMS 1024 /* Static global variables used within this file. */ -static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; +uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; /**< Ports set in promiscuous mode off by default. */ -static int promiscuous_on; +int promiscuous_on; /* Select Longest-Prefix or Exact match. */ static int l3fwd_lpm_on; static int l3fwd_em_on; -static int numa_on = 1; /**< NUMA is enabled by default. */ +int numa_on = 1; /**< NUMA is enabled by default. */ static int parse_ptype; /**< Parse packet type using rx callback, and */ /**< disabled by default */ @@ -90,6 +91,9 @@ uint32_t enabled_port_mask; int ipv6; /**< ipv6 is false by default. */ uint32_t hash_entry_number = HASH_ENTRY_NUMBER_DEFAULT; +/** MAX_JUMBO_PKT_LEN) { + fprintf(stderr, + "invalid maximum packet length\n"); + print_usage(prgname); + return -1; + } + port_conf.rxmode.max_rx_pkt_len = ret; + } + break; + } + + case CMD_LINE_OPT_HASH_ENTRY_NUM_NUM: + ret = parse_hash_entry_number(optarg); + if ((ret > 0) && (ret <= L3FWD_HASH_ENTRIES)) { + hash_entry_number = ret; + } else { + fprintf(stderr, "invalid hash entry number\n"); + print_usage(prgname); + return -1; + } + break; + + case CMD_LINE_OPT_PARSE_PTYPE_NUM: + printf("soft parse-ptype is enabled\n"); + parse_ptype = 1; + break; + + default: + print_usage(prgname); + return -1; + } + } + + /* If both LPM and EM are selected, return error. */ + if (l3fwd_lpm_on && l3fwd_em_on) { + fprintf(stderr, "LPM and EM are mutually exclusive, select only one\n"); + return -1; + } + + /* + * Nothing is selected, pick longest-prefix match + * as default match. + */ + if (!l3fwd_lpm_on && !l3fwd_em_on) { + fprintf(stderr, "LPM or EM none selected, default LPM on\n"); + l3fwd_lpm_on = 1; + } + + /* + * ipv6 and hash flags are valid only for + * exact macth, reset them to default for + * longest-prefix match. + */ + if (l3fwd_lpm_on) { + ipv6 = 0; + hash_entry_number = HASH_ENTRY_NUMBER_DEFAULT; + } + + if (optind >= 0) + argv[optind-1] = prgname; + + ret = optind-1; + optind = 1; /* reset getopt lib */ + return ret; +} + +/* Parse the argument given in the command line of the application */ +static int +parse_args(int argc, char **argv) +{ + int opt; + char **argvopt; + int option_index; + char *end = NULL; + + argvopt = argv; + + /* Error or normal output strings. */ + while ((opt = getopt_long(argc, argvopt, short_options, + lgopts, &option_index)) != EOF) { + /* long options */ + if (opt == CMD_LINE_OPT_DEQUEUE_MODE_NUM) { + dq_mode = strtoul(optarg, &end, 10); + break; + } + } + + if (dq_mode == EVENTDEV_DEQUEUE) + return parse_args_eventdev(argc, argv); + + return parse_args_poll(argc, argv); +} + static void print_ethaddr(const char *name, const struct ether_addr *eth_addr) { @@ -693,7 +904,7 @@ init_mem(unsigned nb_mbuf) } /* Check the link status of all ports in up to 9s, and print them finally */ -static void +void check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ @@ -761,7 +972,7 @@ signal_handler(int signum) } } -static int +int prepare_ptype_parser(uint16_t portid, uint16_t queueid) { if (parse_ptype) { @@ -783,8 +994,8 @@ prepare_ptype_parser(uint16_t portid, uint16_t queueid) return 0; } -int -main(int argc, char **argv) +static int +config_poll(void) { struct lcore_conf *qconf; struct rte_eth_dev_info dev_info; @@ -796,36 +1007,15 @@ main(int argc, char **argv) uint32_t n_tx_queue, nb_lcores; uint8_t nb_rx_queue, queue, socketid; - /* init EAL */ - ret = rte_eal_init(argc, argv); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Invalid EAL parameters\n"); - argc -= ret; - argv += ret; + if (dq_mode != EVENTDEV_DEQUEUE) { - force_quit = false; - signal(SIGINT, signal_handler); - signal(SIGTERM, signal_handler); + if (check_lcore_params() < 0) + rte_exit(EXIT_FAILURE, "check_lcore_params failed\n"); - /* pre-init dst MACs for all ports to 02:00:00:00:00:xx */ - for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { - dest_eth_addr[portid] = - ETHER_LOCAL_ADMIN_ADDR + ((uint64_t)portid << 40); - *(uint64_t *)(val_eth + portid) = dest_eth_addr[portid]; + ret = init_lcore_rx_queues(); + if (ret < 0) + rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n"); } - - /* parse application arguments (after the EAL ones) */ - ret = parse_args(argc, argv); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Invalid L3FWD parameters\n"); - - if (check_lcore_params() < 0) - rte_exit(EXIT_FAILURE, "check_lcore_params failed\n"); - - ret = init_lcore_rx_queues(); - if (ret < 0) - rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n"); - nb_ports = rte_eth_dev_count(); if (check_port_config(nb_ports) < 0) @@ -927,6 +1117,8 @@ main(int argc, char **argv) } printf("\n"); } + if (dq_mode == EVENTDEV_DEQUEUE) + return config_eventdev(); for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { if (rte_lcore_is_enabled(lcore_id) == 0) @@ -1032,3 +1224,35 @@ main(int argc, char **argv) return ret; } + +int +main(int argc, char **argv) +{ + int ret; + uint16_t portid; + + /* init EAL */ + ret = rte_eal_init(argc, argv); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Invalid EAL parameters\n"); + argc -= ret; + argv += ret; + + force_quit = false; + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); + + /* pre-init dst MACs for all ports to 02:00:00:00:00:xx */ + for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { + dest_eth_addr[portid] = + ETHER_LOCAL_ADMIN_ADDR + ((uint64_t)portid << 40); + *(uint64_t *)(val_eth + portid) = dest_eth_addr[portid]; + } + + /* parse application arguments (after the EAL ones) */ + ret = parse_args(argc, argv); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Invalid L3FWD parameters\n"); + + return config_poll(); +} diff --git a/examples/l3fwd/meson.build b/examples/l3fwd/meson.build index 6dd4b90..e6fe32b 100644 --- a/examples/l3fwd/meson.build +++ b/examples/l3fwd/meson.build @@ -8,5 +8,5 @@ deps += ['hash', 'lpm'] sources = files( - 'l3fwd_em.c', 'l3fwd_lpm.c', 'main.c' + 'l3fwd_em.c', 'l3fwd_lpm.c', 'l3fwd_eventdev.c', 'main.c' ) -- 2.9.3