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 84FB142651; Wed, 27 Sep 2023 11:21:56 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id DBA2F4068E; Wed, 27 Sep 2023 11:21:51 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id E1E0E40685 for ; Wed, 27 Sep 2023 11:21:49 +0200 (CEST) Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 38R2ExWf025025; Wed, 27 Sep 2023 02:21:49 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=pfpt0220; bh=TzU+ytelRhmJU1One3B4H7sSgTm81CvL0HmoOaknpBA=; b=D3bDQkFQTRq6Z+Ty63nJ1CPWEtgIc8chIm+1rHrYz2Gj+Unw73ZJICQUNz0Jy9jDU1qM tbC7CcqFPpSEu+oCTEtljF85Wr6GM7fdt8A/sJaBW8rIlkU+Ks0qjw/sZxhZEIFmF52Y oi5VbskAn7DQr2PugNJ+tg0JqsR6gnNMME8vbs9qfcsJnOHTntqTUqDAvyIhll6KvNyS dzO4blwSFOTe+kT5G7PGUG45qbMXSLnDm5G3irhEmPFXpZJ8+DMhg05aZkjlO/NgAv73 r8DQ6S+ETwhhCL0Op0f7SKkXqhN9Ul8YEyCuuxRt0RHsrrr6e3vALVLFtWp4kX7ItL1+ jw== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3tbw5gne85-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Wed, 27 Sep 2023 02:21:48 -0700 Received: from DC5-EXCH02.marvell.com (10.69.176.39) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Wed, 27 Sep 2023 02:21:47 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Wed, 27 Sep 2023 02:21:47 -0700 Received: from localhost.localdomain (unknown [10.28.36.154]) by maili.marvell.com (Postfix) with ESMTP id DE1133F7044; Wed, 27 Sep 2023 02:21:44 -0700 (PDT) From: Rakesh Kudurumalla To: Jerin Jacob , Kiran Kumar K , Nithin Dabilpuram , Zhirun Yan , Pavan Nikhilesh CC: , Rakesh Kudurumalla Subject: [PATCH v4 2/2] node: add UDP v4 support Date: Wed, 27 Sep 2023 14:51:35 +0530 Message-ID: <20230927092135.4006394-2-rkudurumalla@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230927092135.4006394-1-rkudurumalla@marvell.com> References: <20230704105057.25877-1-rkudurumalla@marvell.com> <20230927092135.4006394-1-rkudurumalla@marvell.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-Proofpoint-GUID: SlfWB7YL6I59OpZqMZlhY8k6Sl9eRPEU X-Proofpoint-ORIG-GUID: SlfWB7YL6I59OpZqMZlhY8k6Sl9eRPEU X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-09-27_04,2023-09-26_01,2023-05-22_02 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 IPv4 UDP packets are given to application with specified UDP destination port given by user. Signed-off-by: Rakesh Kudurumalla --- doc/api/doxy-api-index.md | 3 +- doc/guides/prog_guide/graph_lib.rst | 25 ++ .../img/graph_inbuilt_node_flow.svg | 165 ++++++++----- lib/node/meson.build | 2 + lib/node/rte_node_udp4_input_api.h | 60 +++++ lib/node/udp4_input.c | 226 ++++++++++++++++++ lib/node/version.map | 2 + 7 files changed, 417 insertions(+), 66 deletions(-) create mode 100644 lib/node/rte_node_udp4_input_api.h create mode 100644 lib/node/udp4_input.c diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index fdeda13932..96282d3fd0 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -206,7 +206,8 @@ The public API headers are grouped by topics: * graph_nodes: [eth_node](@ref rte_node_eth_api.h), [ip4_node](@ref rte_node_ip4_api.h), - [ip6_node](@ref rte_node_ip6_api.h) + [ip6_node](@ref rte_node_ip6_api.h), + [udp4_input_node](@ref rte_node_udp4_input_api.h) - **basic**: [bitops](@ref rte_bitops.h), diff --git a/doc/guides/prog_guide/graph_lib.rst b/doc/guides/prog_guide/graph_lib.rst index f2e04a68b9..3572560362 100644 --- a/doc/guides/prog_guide/graph_lib.rst +++ b/doc/guides/prog_guide/graph_lib.rst @@ -513,3 +513,28 @@ On packet_type lookup failure, objects are redirected to ``pkt_drop`` node. depth to receive to packets. To achieve home run, node use ``rte_node_stream_move()`` as mentioned in above sections. + +udp4_input +~~~~~~~~~~ +This node is an intermediate node that does udp destination port lookup for +the received ipv4 packets and the result determines each packets next node. + +User registers a new node ``udp4_input`` into graph library during initialization +and attach user specified node as edege to this node using +``rte_node_udp4_usr_node_add()``, and create empty hash table with destination +port and node id as its feilds. + +After successful addition of user node as edege, edge id is returned to the user. + +User would register ``ip4_lookup`` table with specified ip address and 32 bit as mask +for ip filtration using api ``rte_node_ip4_route_add()``. + +After graph is created user would update hash table with custom port with +and previously obtained edge id using API ``rte_node_udp4_dst_port_add()``. + +When packet is received lpm look up is performed if ip is matched the packet +is handed over to ip4_local node, then packet is verified for udp proto and +on success packet is enqueued to ``udp4_input`` node. + +Hash lookup is performed in ``udp4_input`` node with registered destination port +and destination port in UDP packet , on success packet is handed to ``udp_user_node``. diff --git a/doc/guides/prog_guide/img/graph_inbuilt_node_flow.svg b/doc/guides/prog_guide/img/graph_inbuilt_node_flow.svg index b954f6fba1..7c451371a7 100644 --- a/doc/guides/prog_guide/img/graph_inbuilt_node_flow.svg +++ b/doc/guides/prog_guide/img/graph_inbuilt_node_flow.svg @@ -39,192 +39,227 @@ digraph dpdk_inbuilt_nodes_flow { kernel_tx -> kernel_rx [color="red" style="dashed"] ip4_lookup -> ip4_local ip4_local -> pkt_drop [color="cyan" style="dashed"] + ip4_local -> udp4_input [ label="udpv4"] + udp4_input -> udp_user_node + udp4_input -> pkt_drop [color="cyan" style="dashed"] + } --> - - + + dpdk_inbuilt_nodes_flow - + ethdev_rx - -ethdev_rx + +ethdev_rx pkt_cls - -pkt_cls + +pkt_cls ethdev_rx->pkt_cls - - + + kernel_rx - -kernel_rx + +kernel_rx kernel_rx->pkt_cls - - + + ethdev_tx - -ethdev_tx + +ethdev_tx pkt_drop - -pkt_drop + +pkt_drop ethdev_tx->pkt_drop - - + + kernel_tx - -kernel_tx + +kernel_tx kernel_tx->kernel_rx - - + + pkt_cls->pkt_drop - - + + pkt_cls->kernel_tx - - -exception pkts + + +exception pkts ip4_lookup - -ip4_lookup + +ip4_lookup pkt_cls->ip4_lookup - - -ipv4 + + +ipv4 ip6_lookup - -ip6_lookup + +ip6_lookup pkt_cls->ip6_lookup - - -ipv6 + + +ipv6 ip4_lookup->pkt_drop - - + + ip4_rewrite - -ip4_rewrite + +ip4_rewrite ip4_lookup->ip4_rewrite - - + + ip4_local - -ip4_local + +ip4_local ip4_lookup->ip4_local - - + + ip6_lookup->pkt_drop - - + + ip6_rewrite - -ip6_rewrite + +ip6_rewrite ip6_lookup->ip6_rewrite - - + + ip4_rewrite->ethdev_tx - - + + ip4_rewrite->pkt_drop - - + + ip6_rewrite->ethdev_tx - - + + ip6_rewrite->pkt_drop - - + + ip4_local->pkt_drop - - + + + + + +udp4_input + +udp4_input + + + +ip4_local->udp4_input + + +udpv4 + + + +udp4_input->pkt_drop + + + + + +udp_user_node + +udp_user_node + + + +udp4_input->udp_user_node + + diff --git a/lib/node/meson.build b/lib/node/meson.build index c0d5b09e2f..c5b8ee656e 100644 --- a/lib/node/meson.build +++ b/lib/node/meson.build @@ -22,11 +22,13 @@ sources = files( 'null.c', 'pkt_cls.c', 'pkt_drop.c', + 'udp4_input.c', ) headers = files( 'rte_node_eth_api.h', 'rte_node_ip4_api.h', 'rte_node_ip6_api.h', + 'rte_node_udp4_input_api.h', ) # Strict-aliasing rules are violated by uint8_t[] to context size casts. diff --git a/lib/node/rte_node_udp4_input_api.h b/lib/node/rte_node_udp4_input_api.h new file mode 100644 index 0000000000..7217b914ec --- /dev/null +++ b/lib/node/rte_node_udp4_input_api.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2023 Marvell International Ltd. + */ + +#ifndef __INCLUDE_RTE_NODE_UDP4_INPUT_API_H__ +#define __INCLUDE_RTE_NODE_UDP4_INPUT_API_H__ + +/** + * @file rte_node_udp4_input_api.h + * + * @warning + * @b EXPERIMENTAL: + * All functions in this file may be changed or removed without prior notice. + * + * This API allows to control path functions of udp4_* nodes + * like udp4_input. + * + */ +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** + * UDP4 lookup next nodes. + */ +enum rte_node_udp4_input_next { + RTE_NODE_UDP4_INPUT_NEXT_PKT_DROP, + /**< Packet drop node. */ +}; + +/** + * Add usr node to receive udp4 frames. + * + * @param usr_node + * Node registered by user to receive data. + */ +__rte_experimental +int rte_node_udp4_usr_node_add(const char *usr_node); + +/** + * Add udpv4 dst_port to lookup table. + * + * @param dst_port + * Dst Port of packet to be added for consumption. + * @param next_node + * Next node packet to be added for consumption. + * @return + * 0 on success, negative otherwise. + */ +__rte_experimental +int rte_node_udp4_dst_port_add(uint32_t dst_port, rte_edge_t next_node); + +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_RTE_NODE_UDP4_API_H__ */ diff --git a/lib/node/udp4_input.c b/lib/node/udp4_input.c new file mode 100644 index 0000000000..80cedce548 --- /dev/null +++ b/lib/node/udp4_input.c @@ -0,0 +1,226 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2023 Marvell International Ltd. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "rte_node_udp4_input_api.h" + +#include "node_private.h" + +#define UDP4_INPUT_HASH_TBL_SIZE 1024 + +#define UDP4_INPUT_NODE_HASH(ctx) \ + (((struct udp4_input_node_ctx *)ctx)->hash) + +#define UDP4_INPUT_NODE_NEXT_INDEX(ctx) \ + (((struct udp4_input_node_ctx *)ctx)->next_index) + + +/* UDP4 input global data struct */ +struct udp4_input_node_main { + struct rte_hash *hash_tbl[RTE_MAX_NUMA_NODES]; +}; + +static struct udp4_input_node_main udp4_input_nm; + +struct udp4_input_node_ctx { + /* Socket's Hash table */ + struct rte_hash *hash; + /* Cached next index */ + uint16_t next_index; +}; + +struct flow_key { + uint32_t prt_dst; +}; + +static struct rte_hash_parameters udp4_params = { + .entries = UDP4_INPUT_HASH_TBL_SIZE, + .key_len = sizeof(uint32_t), + .hash_func = rte_jhash, + .hash_func_init_val = 0, + .socket_id = 0, +}; + +int +rte_node_udp4_dst_port_add(uint32_t dst_port, rte_edge_t next_node) +{ + uint8_t socket; + int rc; + + for (socket = 0; socket < RTE_MAX_NUMA_NODES; socket++) { + if (!udp4_input_nm.hash_tbl[socket]) + continue; + + rc = rte_hash_add_key_data(udp4_input_nm.hash_tbl[socket], + &dst_port, (void *)(uintptr_t)next_node); + if (rc < 0) { + node_err("udp4_lookup", "Failed to add key for sock %u, rc=%d", + socket, rc); + return rc; + } + } + return 0; +} + +int +rte_node_udp4_usr_node_add(const char *usr_node) +{ + const char *next_nodes = usr_node; + rte_node_t udp4_input_node_id, count; + + udp4_input_node_id = rte_node_from_name("udp4_input"); + count = rte_node_edge_update(udp4_input_node_id, RTE_EDGE_ID_INVALID, + &next_nodes, 1); + if (count == 0) { + node_dbg("udp4_input", "Adding usr node as edge to udp4_input failed"); + return count; + } + count = rte_node_edge_count(udp4_input_node_id) - 1; + return count; +} + +static int +setup_udp4_dstprt_hash(struct udp4_input_node_main *nm, int socket) +{ + struct rte_hash_parameters *hash_udp4 = &udp4_params; + char s[RTE_HASH_NAMESIZE]; + + /* One Hash table per socket */ + if (nm->hash_tbl[socket]) + return 0; + + /* create Hash table */ + snprintf(s, sizeof(s), "UDP4_INPUT_HASH_%d", socket); + hash_udp4->name = s; + hash_udp4->socket_id = socket; + nm->hash_tbl[socket] = rte_hash_create(hash_udp4); + if (nm->hash_tbl[socket] == NULL) + return -rte_errno; + + return 0; +} + +static int +udp4_input_node_init(const struct rte_graph *graph, struct rte_node *node) +{ + uint16_t socket, lcore_id; + static uint8_t init_once; + int rc; + + RTE_SET_USED(graph); + RTE_BUILD_BUG_ON(sizeof(struct udp4_input_node_ctx) > RTE_NODE_CTX_SZ); + + if (!init_once) { + + /* Setup HASH tables for all sockets */ + RTE_LCORE_FOREACH(lcore_id) + { + socket = rte_lcore_to_socket_id(lcore_id); + rc = setup_udp4_dstprt_hash(&udp4_input_nm, socket); + if (rc) { + node_err("udp4_lookup", + "Failed to setup hash tbl for sock %u, rc=%d", + socket, rc); + return rc; + } + } + init_once = 1; + } + + UDP4_INPUT_NODE_HASH(node->ctx) = udp4_input_nm.hash_tbl[graph->socket]; + + node_dbg("udp4_input", "Initialized udp4_input node"); + return 0; +} + +static uint16_t +udp4_input_node_process_scalar(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + struct rte_hash *hash_tbl_handle = UDP4_INPUT_NODE_HASH(node->ctx); + rte_edge_t next_index, udplookup_node; + struct rte_udp_hdr *pkt_udp_hdr; + uint16_t last_spec = 0; + void **to_next, **from; + struct rte_mbuf *mbuf; + uint16_t held = 0; + uint16_t next = 0; + int i, rc; + + /* Speculative next */ + next_index = UDP4_INPUT_NODE_NEXT_INDEX(node->ctx); + + from = objs; + + to_next = rte_node_next_stream_get(graph, node, next_index, nb_objs); + for (i = 0; i < nb_objs; i++) { + struct flow_key key_port; + + mbuf = (struct rte_mbuf *)objs[i]; + pkt_udp_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_udp_hdr *, + sizeof(struct rte_ether_hdr) + + sizeof(struct rte_ipv4_hdr)); + + key_port.prt_dst = rte_cpu_to_be_16(pkt_udp_hdr->dst_port); + rc = rte_hash_lookup_data(hash_tbl_handle, + &key_port.prt_dst, + (void **)&udplookup_node); + next = (rc < 0) ? RTE_NODE_UDP4_INPUT_NEXT_PKT_DROP + : udplookup_node; + + if (unlikely(next_index != next)) { + /* Copy things successfully speculated till now */ + rte_memcpy(to_next, from, last_spec * sizeof(from[0])); + from += last_spec; + to_next += last_spec; + held += last_spec; + last_spec = 0; + + rte_node_enqueue_x1(graph, node, next, from[0]); + from += 1; + } else { + last_spec += 1; + } + } + /* !!! Home run !!! */ + if (likely(last_spec == nb_objs)) { + rte_node_next_stream_move(graph, node, next_index); + return nb_objs; + } + held += last_spec; + rte_memcpy(to_next, from, last_spec * sizeof(from[0])); + rte_node_next_stream_put(graph, node, next_index, held); + /* Save the last next used */ + UDP4_INPUT_NODE_NEXT_INDEX(node->ctx) = next; + + return nb_objs; +} + +static struct rte_node_register udp4_input_node = { + .process = udp4_input_node_process_scalar, + .name = "udp4_input", + + .init = udp4_input_node_init, + + .nb_edges = RTE_NODE_UDP4_INPUT_NEXT_PKT_DROP + 1, + .next_nodes = { + [RTE_NODE_UDP4_INPUT_NEXT_PKT_DROP] = "pkt_drop", + }, +}; + +RTE_NODE_REGISTER(udp4_input_node); diff --git a/lib/node/version.map b/lib/node/version.map index 40df308bfe..c51befce09 100644 --- a/lib/node/version.map +++ b/lib/node/version.map @@ -6,6 +6,8 @@ EXPERIMENTAL { rte_node_ip4_rewrite_add; rte_node_ip6_rewrite_add; rte_node_ip6_route_add; + rte_node_udp4_usr_node_add; + rte_node_udp4_dst_port_add; rte_node_logtype; local: *; }; -- 2.25.1