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 CE6BF42B21; Tue, 16 May 2023 11:13:13 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id A328240C35; Tue, 16 May 2023 11:13:13 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by mails.dpdk.org (Postfix) with ESMTP id 880674068E for ; Tue, 16 May 2023 11:13:12 +0200 (CEST) Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 34G88KtB027952 for ; Tue, 16 May 2023 02:13:11 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : mime-version : content-transfer-encoding : content-type; s=pfpt0220; bh=9Y+7jKGmX5U1n/RfQtu2mHXgS/iCiRTAiaW//9uPKB4=; b=dyO4BMWzAtvtXw/gfPU9pZfjqncviDSHvUpz+7XDMEsdl3HGagmQ9cqvXOTEjUzONKoa hD2DAF/PxlZkAPKWseUNINlwGcgZE1tqh98A4Ufr3lwSq3Fh6qHOezg0ZM922/Kmh7OD P3rouCrcuG28hfNX8dcx2sReMqj6YZHfrboBM4JJGDwmUba1FVtvLN7FftmkX2ykSo+c /hmiqL/r6baEvMGAfdAFFbGSGlBdSX0Nc9Lhf1sF2pd5PA+eWyA4+dZqvEwoCKR8xJhG FDDp87WerYcNymJ3xoqI+idPXDTCDoRIrjdqPJDclfmHydT7L4MU596RrwfiDyxogTfA oA== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3qja2jrm51-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 16 May 2023 02:13:11 -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; Tue, 16 May 2023 02:12:16 -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; Tue, 16 May 2023 02:12:16 -0700 Received: from localhost.localdomain (unknown [10.28.36.157]) by maili.marvell.com (Postfix) with ESMTP id 711843F70A5; Tue, 16 May 2023 02:12:14 -0700 (PDT) From: Amit Prakash Shukla To: Jerin Jacob , Kiran Kumar K , Nithin Dabilpuram , Pavan Nikhilesh CC: , Subject: [PATCH 1/3] lib: add IPv6 lookup node Date: Tue, 16 May 2023 14:41:54 +0530 Message-ID: <20230516091157.1560829-1-amitprakashs@marvell.com> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-Proofpoint-GUID: yOb0lKwMLxAo0R9dSZhCmMBK79rbr7d6 X-Proofpoint-ORIG-GUID: yOb0lKwMLxAo0R9dSZhCmMBK79rbr7d6 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.254,Aquarius:18.0.957,Hydra:6.0.573,FMLib:17.11.170.22 definitions=2023-05-16_02,2023-05-05_01,2023-02-09_01 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 From: Sunil Kumar Kori Similar to IPv4 lookup node, patch adds IPv6 lookup node. Signed-off-by: Sunil Kumar Kori --- doc/guides/prog_guide/graph_lib.rst | 13 ++ lib/node/ip6_lookup.c | 225 ++++++++++++++++++++++++++++ lib/node/meson.build | 3 +- lib/node/node_private.h | 3 +- lib/node/pkt_cls.c | 14 ++ lib/node/pkt_cls_priv.h | 1 + lib/node/rte_node_ip6_api.h | 80 ++++++++++ lib/node/version.map | 2 + 8 files changed, 339 insertions(+), 2 deletions(-) create mode 100644 lib/node/ip6_lookup.c create mode 100644 lib/node/rte_node_ip6_api.h diff --git a/doc/guides/prog_guide/graph_lib.rst b/doc/guides/prog_guide/graph_lib.rst index 1cfdc86433..1f70d63628 100644 --- a/doc/guides/prog_guide/graph_lib.rst +++ b/doc/guides/prog_guide/graph_lib.rst @@ -388,6 +388,19 @@ to determine the L2 header to be written to the packet before sending the packet out to a particular ethdev_tx node. ``rte_node_ip4_rewrite_add()`` is control path API to add next-hop info. +ip6_lookup +~~~~~~~~~~ +This node is an intermediate node that does LPM lookup for the received +ipv6 packets and the result determines each packets next node. + +On successful LPM lookup, the result contains the ``next_node`` id and +``next-hop`` id with which the packet needs to be further processed. + +On LPM lookup failure, objects are redirected to pkt_drop node. +``rte_node_ip6_route_add()`` is control path API to add ipv6 routes. +To achieve home run, node use ``rte_node_stream_move()`` as mentioned in above +sections. + null ~~~~ This node ignores the set of objects passed to it and reports that all are diff --git a/lib/node/ip6_lookup.c b/lib/node/ip6_lookup.c new file mode 100644 index 0000000000..94a9c404b4 --- /dev/null +++ b/lib/node/ip6_lookup.c @@ -0,0 +1,225 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2023 Marvell. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "rte_node_ip6_api.h" + +#include "node_private.h" + +#define IPV6_L3FWD_LPM_MAX_RULES 1024 +#define IPV6_L3FWD_LPM_NUMBER_TBL8S (1 << 8) + +/* IP6 Lookup global data struct */ +struct ip6_lookup_node_main { + struct rte_lpm6 *lpm_tbl[RTE_MAX_NUMA_NODES]; +}; + +struct ip6_lookup_node_ctx { + /* Socket's LPM table */ + struct rte_lpm6 *lpm6; + /* Dynamic offset to mbuf priv1 */ + int mbuf_priv1_off; +}; + +int ip6_node_mbuf_priv1_dynfield_offset = -1; + +static struct ip6_lookup_node_main ip6_lookup_nm; + +#define IP6_LOOKUP_NODE_LPM(ctx) \ + (((struct ip6_lookup_node_ctx *)ctx)->lpm6) + +#define IP6_LOOKUP_NODE_PRIV1_OFF(ctx) \ + (((struct ip6_lookup_node_ctx *)ctx)->mbuf_priv1_off) + +static uint16_t +ip6_lookup_node_process_scalar(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + struct rte_lpm6 *lpm6 = IP6_LOOKUP_NODE_LPM(node->ctx); + const int dyn = IP6_LOOKUP_NODE_PRIV1_OFF(node->ctx); + struct rte_ipv6_hdr *ipv6_hdr; + void **to_next, **from; + uint16_t last_spec = 0; + struct rte_mbuf *mbuf; + rte_edge_t next_index; + uint16_t held = 0; + uint32_t drop_nh; + int i, rc; + + /* Speculative next */ + next_index = RTE_NODE_IP6_LOOKUP_NEXT_REWRITE; + /* Drop node */ + drop_nh = ((uint32_t)RTE_NODE_IP6_LOOKUP_NEXT_PKT_DROP) << 16; + from = objs; + + /* Get stream for the speculated next node */ + to_next = rte_node_next_stream_get(graph, node, next_index, nb_objs); + for (i = 0; i < nb_objs; i++) { + uint32_t next_hop; + uint16_t next; + + mbuf = (struct rte_mbuf *)objs[i]; + + /* Extract DIP of mbuf0 */ + ipv6_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv6_hdr *, + sizeof(struct rte_ether_hdr)); + /* Extract hop_limits as ipv6 hdr is in cache */ + node_mbuf_priv1(mbuf, dyn)->ttl = ipv6_hdr->hop_limits; + + rc = rte_lpm6_lookup(lpm6, ipv6_hdr->dst_addr, &next_hop); + next_hop = (rc == 0) ? next_hop : drop_nh; + + node_mbuf_priv1(mbuf, dyn)->nh = (uint16_t)next_hop; + next_hop = next_hop >> 16; + next = (uint16_t)next_hop; + + 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); + + return nb_objs; +} + +int +rte_node_ip6_route_add(const uint8_t *ip, uint8_t depth, uint16_t next_hop, + enum rte_node_ip6_lookup_next next_node) +{ + char abuf[INET6_ADDRSTRLEN]; + struct in6_addr in6; + uint8_t socket; + uint32_t val; + int ret; + + memcpy(in6.s6_addr, ip, RTE_LPM6_IPV6_ADDR_SIZE); + inet_ntop(AF_INET6, &in6, abuf, sizeof(abuf)); + /* Embedded next node id into 24 bit next hop */ + val = ((next_node << 16) | next_hop) & ((1ull << 24) - 1); + node_dbg("ip6_lookup", "LPM: Adding route %s / %d nh (0x%x)", abuf, + depth, val); + + for (socket = 0; socket < RTE_MAX_NUMA_NODES; socket++) { + if (!ip6_lookup_nm.lpm_tbl[socket]) + continue; + + ret = rte_lpm6_add(ip6_lookup_nm.lpm_tbl[socket], ip, depth, + val); + if (ret < 0) { + node_err("ip6_lookup", + "Unable to add entry %s / %d nh (%x) to LPM " + "table on sock %d, rc=%d\n", + abuf, depth, val, socket, ret); + return ret; + } + } + + return 0; +} + +static int +setup_lpm6(struct ip6_lookup_node_main *nm, int socket) +{ + struct rte_lpm6_config config_ipv6; + char s[RTE_LPM6_NAMESIZE]; + + /* One LPM table per socket */ + if (nm->lpm_tbl[socket]) + return 0; + + /* create the LPM table */ + config_ipv6.max_rules = IPV6_L3FWD_LPM_MAX_RULES; + config_ipv6.number_tbl8s = IPV6_L3FWD_LPM_NUMBER_TBL8S; + config_ipv6.flags = 0; + snprintf(s, sizeof(s), "IPV6_L3FWD_LPM_%d", socket); + nm->lpm_tbl[socket] = rte_lpm6_create(s, socket, &config_ipv6); + if (nm->lpm_tbl[socket] == NULL) + return -rte_errno; + + return 0; +} + +static int +ip6_lookup_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 ip6_lookup_node_ctx) > RTE_NODE_CTX_SZ); + + if (!init_once) { + ip6_node_mbuf_priv1_dynfield_offset = + rte_mbuf_dynfield_register( + &node_mbuf_priv1_dynfield_desc); + if (ip6_node_mbuf_priv1_dynfield_offset < 0) + return -rte_errno; + + /* Setup LPM tables for all sockets */ + RTE_LCORE_FOREACH(lcore_id) + { + socket = rte_lcore_to_socket_id(lcore_id); + rc = setup_lpm6(&ip6_lookup_nm, socket); + if (rc) { + node_err("ip6_lookup", + "Failed to setup lpm6 tbl for " + "sock %u, rc=%d", socket, rc); + return rc; + } + } + init_once = 1; + } + + /* Update socket's LPM and mbuf dyn priv1 offset in node ctx */ + IP6_LOOKUP_NODE_LPM(node->ctx) = ip6_lookup_nm.lpm_tbl[graph->socket]; + IP6_LOOKUP_NODE_PRIV1_OFF(node->ctx) = + ip6_node_mbuf_priv1_dynfield_offset; + + node_dbg("ip6_lookup", "Initialized ip6_lookup node"); + + return 0; +} + +static struct rte_node_register ip6_lookup_node = { + .process = ip6_lookup_node_process_scalar, + .name = "ip6_lookup", + + .init = ip6_lookup_node_init, + + .nb_edges = RTE_NODE_IP6_LOOKUP_NEXT_MAX, + .next_nodes = { + [RTE_NODE_IP6_LOOKUP_NEXT_REWRITE] = "ip6_rewrite", + [RTE_NODE_IP6_LOOKUP_NEXT_PKT_DROP] = "pkt_drop", + }, +}; + +RTE_NODE_REGISTER(ip6_lookup_node); diff --git a/lib/node/meson.build b/lib/node/meson.build index dbdf673c86..cd30847a0b 100644 --- a/lib/node/meson.build +++ b/lib/node/meson.build @@ -12,13 +12,14 @@ sources = files( 'ethdev_rx.c', 'ethdev_tx.c', 'ip4_lookup.c', + 'ip6_lookup.c', 'ip4_rewrite.c', 'log.c', 'null.c', 'pkt_cls.c', 'pkt_drop.c', ) -headers = files('rte_node_ip4_api.h', 'rte_node_eth_api.h') +headers = files('rte_node_ip4_api.h', 'rte_node_ip6_api.h', 'rte_node_eth_api.h') # Strict-aliasing rules are violated by uint8_t[] to context size casts. cflags += '-fno-strict-aliasing' deps += ['graph', 'mbuf', 'lpm', 'ethdev', 'mempool', 'cryptodev'] diff --git a/lib/node/node_private.h b/lib/node/node_private.h index 8c73d5dc10..27555cbfd8 100644 --- a/lib/node/node_private.h +++ b/lib/node/node_private.h @@ -26,7 +26,7 @@ extern int rte_node_logtype; */ struct node_mbuf_priv1 { union { - /* IP4 rewrite */ + /* IP4/IP6 rewrite */ struct { uint16_t nh; uint16_t ttl; @@ -43,6 +43,7 @@ static const struct rte_mbuf_dynfield node_mbuf_priv1_dynfield_desc = { .align = __alignof__(struct node_mbuf_priv1), }; extern int node_mbuf_priv1_dynfield_offset; +extern int ip6_node_mbuf_priv1_dynfield_offset; /** * Node mbuf private area 2. diff --git a/lib/node/pkt_cls.c b/lib/node/pkt_cls.c index 3e75f2cf78..a8302b8d28 100644 --- a/lib/node/pkt_cls.c +++ b/lib/node/pkt_cls.c @@ -24,6 +24,19 @@ static const uint8_t p_nxt[256] __rte_cache_aligned = { [RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L2_ETHER] = PKT_CLS_NEXT_IP4_LOOKUP, + + [RTE_PTYPE_L3_IPV6] = PKT_CLS_NEXT_IP6_LOOKUP, + + [RTE_PTYPE_L3_IPV6_EXT] = PKT_CLS_NEXT_IP6_LOOKUP, + + [RTE_PTYPE_L3_IPV6_EXT_UNKNOWN] = PKT_CLS_NEXT_IP6_LOOKUP, + + [RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L2_ETHER] = PKT_CLS_NEXT_IP6_LOOKUP, + + [RTE_PTYPE_L3_IPV6_EXT | RTE_PTYPE_L2_ETHER] = PKT_CLS_NEXT_IP6_LOOKUP, + + [RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_L2_ETHER] = + PKT_CLS_NEXT_IP6_LOOKUP, }; static uint16_t @@ -216,6 +229,7 @@ struct rte_node_register pkt_cls_node = { /* Pkt drop node starts at '0' */ [PKT_CLS_NEXT_PKT_DROP] = "pkt_drop", [PKT_CLS_NEXT_IP4_LOOKUP] = "ip4_lookup", + [PKT_CLS_NEXT_IP6_LOOKUP] = "ip6_lookup", }, }; RTE_NODE_REGISTER(pkt_cls_node); diff --git a/lib/node/pkt_cls_priv.h b/lib/node/pkt_cls_priv.h index 6f5374f0be..16135807a1 100644 --- a/lib/node/pkt_cls_priv.h +++ b/lib/node/pkt_cls_priv.h @@ -13,6 +13,7 @@ struct pkt_cls_node_ctx { enum pkt_cls_next_nodes { PKT_CLS_NEXT_PKT_DROP, PKT_CLS_NEXT_IP4_LOOKUP, + PKT_CLS_NEXT_IP6_LOOKUP, PKT_CLS_NEXT_MAX, }; diff --git a/lib/node/rte_node_ip6_api.h b/lib/node/rte_node_ip6_api.h new file mode 100644 index 0000000000..1696ed154d --- /dev/null +++ b/lib/node/rte_node_ip6_api.h @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2023 Marvell. + */ + +#ifndef __INCLUDE_RTE_NODE_IP6_API_H__ +#define __INCLUDE_RTE_NODE_IP6_API_H__ + +/** + * @file rte_node_ip6_api.h + * + * @warning + * @b EXPERIMENTAL: + * All functions in this file may be changed or removed without prior notice. + * + * This API allows to do control path functions of ip6_* nodes + * like ip6_lookup, ip6_rewrite. + * + */ +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** + * IP6 lookup next nodes. + */ +enum rte_node_ip6_lookup_next { + RTE_NODE_IP6_LOOKUP_NEXT_REWRITE, + /**< Rewrite node. */ + RTE_NODE_IP6_LOOKUP_NEXT_PKT_DROP, + /**< Packet drop node. */ + RTE_NODE_IP6_LOOKUP_NEXT_MAX, + /**< Number of next nodes of lookup node. */ +}; + +/** + * Add ipv6 route to lookup table. + * + * @param ip + * IPv6 address of route to be added. + * @param depth + * Depth of the rule to be added. + * @param next_hop + * Next hop id of the rule result to be added. + * @param next_node + * Next node to redirect traffic to. + * + * @return + * 0 on success, negative otherwise. + */ +__rte_experimental +int rte_node_ip6_route_add(const uint8_t *ip, uint8_t depth, uint16_t next_hop, + enum rte_node_ip6_lookup_next next_node); + +/** + * Add a next hop's rewrite data. + * + * @param next_hop + * Next hop id to add rewrite data to. + * @param rewrite_data + * Rewrite data. + * @param rewrite_len + * Length of rewrite data. + * @param dst_port + * Destination port to redirect traffic to. + * + * @return + * 0 on success, negative otherwise. + */ +__rte_experimental +int rte_node_ip6_rewrite_add(uint16_t next_hop, uint8_t *rewrite_data, + uint8_t rewrite_len, uint16_t dst_port); + +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_RTE_NODE_IP6_API_H__ */ diff --git a/lib/node/version.map b/lib/node/version.map index a799b0d389..40df308bfe 100644 --- a/lib/node/version.map +++ b/lib/node/version.map @@ -4,6 +4,8 @@ EXPERIMENTAL { rte_node_eth_config; rte_node_ip4_route_add; rte_node_ip4_rewrite_add; + rte_node_ip6_rewrite_add; + rte_node_ip6_route_add; rte_node_logtype; local: *; }; -- 2.25.1