From patchwork Thu May 18 15:56:52 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amit Prakash Shukla X-Patchwork-Id: 127020 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 90D4842AF1; Thu, 18 May 2023 17:57:05 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 812BB40A8A; Thu, 18 May 2023 17:57:05 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id 346304014F for ; Thu, 18 May 2023 17:57:04 +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 34IA40oZ012881 for ; Thu, 18 May 2023 08:57:03 -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=gM0SOmI/VPuKUdKHKUSQZYsx4sBWFX63aHCFYos2+7M=; b=IustBxjXWP3j06QPeZMyM0ncysQ/Bxt8HV/sExRDmM4S1Qqf2ApTPvdXsB7j+WBwJwmm 3BEkJRq7BnMklP/nuCPVSyYtkzRdi2B7NmhBNczxyYeo+ZkstAkNcQHzXFMNvTe1ViPH s/IIhTOIGvWYwBJ7g4h7thbYuBBO1TG7XtNeWENnRpOmMMYFmDrXHSioZgiqrAvjCXLF rUjwLJGpWdnUWyYirLnbJ9ia9djGgWWnodvG5w9RC5CflWiABcnh5KNplzFf7/Aikn2L eYLYIC68jPnJk37fFcHITSs3l7AnLucPMstE7AnhLM8n8/kdmWWtQynFryJ4cTpQRwoG jA== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3qn7jbbmx2-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Thu, 18 May 2023 08:57:03 -0700 Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Thu, 18 May 2023 08:57:01 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Thu, 18 May 2023 08:57:01 -0700 Received: from localhost.localdomain (unknown [10.28.36.157]) by maili.marvell.com (Postfix) with ESMTP id 399DB3F7066; Thu, 18 May 2023 08:56:58 -0700 (PDT) From: Amit Prakash Shukla To: Jerin Jacob , Kiran Kumar K , Nithin Dabilpuram , Pavan Nikhilesh CC: , , Amit Prakash Shukla Subject: [PATCH v2 1/3] lib: add IPv6 lookup node Date: Thu, 18 May 2023 21:26:52 +0530 Message-ID: <20230518155654.1756576-1-amitprakashs@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230516091157.1560829-1-amitprakashs@marvell.com> References: <20230516091157.1560829-1-amitprakashs@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: TlqDdAXeg40z98eyAg0EYY57OYOIRO54 X-Proofpoint-ORIG-GUID: TlqDdAXeg40z98eyAg0EYY57OYOIRO54 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-18_12,2023-05-17_02,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 Signed-off-by: Amit Prakash Shukla --- v2: - Performance related changes doc/guides/prog_guide/graph_lib.rst | 13 + lib/node/ip6_lookup.c | 374 ++++++++++++++++++++++++++++ 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, 488 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..a377c06072 --- /dev/null +++ b/lib/node/ip6_lookup.c @@ -0,0 +1,374 @@ +/* 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_mbuf *mbuf0, *mbuf1, *mbuf2, *mbuf3, **pkts; + 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; + rte_edge_t next_index; + uint16_t n_left_from; + 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; + + pkts = (struct rte_mbuf **)objs; + from = objs; + n_left_from = nb_objs; + + for (i = OBJS_PER_CLINE; i < RTE_GRAPH_BURST_SIZE; i += OBJS_PER_CLINE) + rte_prefetch0(&objs[i]); + + for (i = 0; i < 4 && i < n_left_from; i++) + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[i], void *, + sizeof(struct rte_ether_hdr))); + + /* Get stream for the speculated next node */ + to_next = rte_node_next_stream_get(graph, node, next_index, nb_objs); + while (n_left_from >= 4) { +#if RTE_GRAPH_BURST_SIZE > 64 + /* Prefetch next-next mbufs */ + if (likely(n_left_from > 11)) { + rte_prefetch0(pkts[8]); + rte_prefetch0(pkts[9]); + rte_prefetch0(pkts[10]); + rte_prefetch0(pkts[11]); + } +#endif + /* Prefetch next mbuf data */ + if (likely(n_left_from > 7)) { + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[4], void *, + sizeof(struct rte_ether_hdr))); + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[5], void *, + sizeof(struct rte_ether_hdr))); + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[6], void *, + sizeof(struct rte_ether_hdr))); + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[7], void *, + sizeof(struct rte_ether_hdr))); + } + + mbuf0 = pkts[0]; + mbuf1 = pkts[1]; + mbuf2 = pkts[2]; + mbuf3 = pkts[3]; + + pkts += 4; + n_left_from -= 4; + + uint8_t ip_batch[4][16]; + int32_t next_hop[4]; + uint16_t next[4]; + + /* Extract DIP of mbuf0 */ + ipv6_hdr = rte_pktmbuf_mtod_offset(mbuf0, struct rte_ipv6_hdr *, + sizeof(struct rte_ether_hdr)); + /* Extract hop_limits as ipv6 hdr is in cache */ + node_mbuf_priv1(mbuf0, dyn)->ttl = ipv6_hdr->hop_limits; + rte_memcpy(ip_batch[0], ipv6_hdr->dst_addr, 16); + + /* Extract DIP of mbuf1 */ + ipv6_hdr = rte_pktmbuf_mtod_offset(mbuf1, struct rte_ipv6_hdr *, + sizeof(struct rte_ether_hdr)); + /* Extract hop_limits as ipv6 hdr is in cache */ + node_mbuf_priv1(mbuf1, dyn)->ttl = ipv6_hdr->hop_limits; + rte_memcpy(ip_batch[1], ipv6_hdr->dst_addr, 16); + + /* Extract DIP of mbuf2 */ + ipv6_hdr = rte_pktmbuf_mtod_offset(mbuf2, struct rte_ipv6_hdr *, + sizeof(struct rte_ether_hdr)); + /* Extract hop_limits as ipv6 hdr is in cache */ + node_mbuf_priv1(mbuf2, dyn)->ttl = ipv6_hdr->hop_limits; + rte_memcpy(ip_batch[2], ipv6_hdr->dst_addr, 16); + + /* Extract DIP of mbuf3 */ + ipv6_hdr = rte_pktmbuf_mtod_offset(mbuf3, struct rte_ipv6_hdr *, + sizeof(struct rte_ether_hdr)); + /* Extract hop_limits as ipv6 hdr is in cache */ + node_mbuf_priv1(mbuf3, dyn)->ttl = ipv6_hdr->hop_limits; + rte_memcpy(ip_batch[3], ipv6_hdr->dst_addr, 16); + + rc = rte_lpm6_lookup_bulk_func(lpm6, ip_batch, next_hop, 4); + + next_hop[0] = (next_hop[0] < 0) ? (int32_t)drop_nh : next_hop[0]; + node_mbuf_priv1(mbuf0, dyn)->nh = (uint16_t)next_hop[0]; + next[0] = (uint16_t)(next_hop[0] >> 16); + + next_hop[1] = (next_hop[1] < 0) ? (int32_t)drop_nh : next_hop[1]; + node_mbuf_priv1(mbuf1, dyn)->nh = (uint16_t)next_hop[1]; + next[1] = (uint16_t)(next_hop[1] >> 16); + + next_hop[2] = (next_hop[2] < 0) ? (int32_t)drop_nh : next_hop[2]; + node_mbuf_priv1(mbuf2, dyn)->nh = (uint16_t)next_hop[2]; + next[2] = (uint16_t)(next_hop[2] >> 16); + + next_hop[3] = (next_hop[3] < 0) ? (int32_t)drop_nh : next_hop[3]; + node_mbuf_priv1(mbuf3, dyn)->nh = (uint16_t)next_hop[3]; + next[3] = (uint16_t)(next_hop[3] >> 16); + + rte_edge_t fix_spec = ((next_index == next[0]) && + (next_index == next[1]) && + (next_index == next[2]) && + (next_index == next[3])); + + if (unlikely(fix_spec == 0)) { + /* 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; + + /* Next0 */ + if (next_index == next[0]) { + to_next[0] = from[0]; + to_next++; + held++; + } else { + rte_node_enqueue_x1(graph, node, next[0], from[0]); + } + + /* Next1 */ + if (next_index == next[1]) { + to_next[0] = from[1]; + to_next++; + held++; + } else { + rte_node_enqueue_x1(graph, node, next[1], from[1]); + } + + /* Next2 */ + if (next_index == next[2]) { + to_next[0] = from[2]; + to_next++; + held++; + } else { + rte_node_enqueue_x1(graph, node, next[2], from[2]); + } + + /* Next3 */ + if (next_index == next[3]) { + to_next[0] = from[3]; + to_next++; + held++; + } else { + rte_node_enqueue_x1(graph, node, next[3], from[3]); + } + + from += 4; + } else { + last_spec += 4; + } + } + + while (n_left_from > 0) { + uint32_t next_hop; + uint16_t next0; + + mbuf0 = pkts[0]; + + pkts += 1; + n_left_from -= 1; + + /* Extract DIP of mbuf0 */ + ipv6_hdr = rte_pktmbuf_mtod_offset(mbuf0, struct rte_ipv6_hdr *, + sizeof(struct rte_ether_hdr)); + /* Extract ttl as ipv6 hdr is in cache */ + node_mbuf_priv1(mbuf0, 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(mbuf0, dyn)->nh = (uint16_t)next_hop; + next_hop = next_hop >> 16; + next0 = (uint16_t)next_hop; + + if (unlikely(next_index ^ next0)) { + /* 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, next0, 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: *; }; From patchwork Thu May 18 15:56:53 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amit Prakash Shukla X-Patchwork-Id: 127021 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 0160942AF1; Thu, 18 May 2023 17:57:11 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id EA3F942BFE; Thu, 18 May 2023 17:57:10 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id 3CB9A42BFE for ; Thu, 18 May 2023 17:57:09 +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 34IAO6BP013340 for ; Thu, 18 May 2023 08:57:08 -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=OJzlWCjp6j9bCoBiPTLd3bgJXpRDsXCNioK3lECZw2A=; b=avs52chgVH3/c86wrmULv2CgdrYE5+wKIx8vf/qVP2HqP3kINmAk0XWRJd9QRbNyB4DU Ee3U2oFXfTLHfshaNlDjWpLI6b3fHqZWrCZGm3oSATYhFZDycZN1sbReEOk+llxK3QiB o1QivIO7W7a1qlFloBhq7a3yVNFtcX7MAG0lG2PVXORfNuFxnpm2SgPqEcOXYLOKPLWc BR/7dDzZklMvYZk2AkUypeLrW8fA+8vJKim/K56WQzKQbcn+sgYf1CvWD56KxTVgdm2H iR7FekZzZOChzXRVHVurgLgwaUqnbBmEVyyoBHzcqm2ki3h5aGvKhbtbBAVHrX1EMqPj Sg== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3qn7jbbmxr-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Thu, 18 May 2023 08:57:07 -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; Thu, 18 May 2023 08:57:05 -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; Thu, 18 May 2023 08:57:06 -0700 Received: from localhost.localdomain (unknown [10.28.36.157]) by maili.marvell.com (Postfix) with ESMTP id CB20A3F7050; Thu, 18 May 2023 08:57:03 -0700 (PDT) From: Amit Prakash Shukla To: Jerin Jacob , Kiran Kumar K , Nithin Dabilpuram , Pavan Nikhilesh CC: , , Amit Prakash Shukla Subject: [PATCH v2 2/3] lib: add IPv6 rewrite node Date: Thu, 18 May 2023 21:26:53 +0530 Message-ID: <20230518155654.1756576-2-amitprakashs@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230518155654.1756576-1-amitprakashs@marvell.com> References: <20230516091157.1560829-1-amitprakashs@marvell.com> <20230518155654.1756576-1-amitprakashs@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: DIZm0mNKlBHLkGJNetJlXD1ELLIr64Qn X-Proofpoint-ORIG-GUID: DIZm0mNKlBHLkGJNetJlXD1ELLIr64Qn 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-18_12,2023-05-17_02,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 Similar to IPv4 rewrite node, patch adds IPv6 rewrite node. Signed-off-by: Amit Prakash Shukla --- v2: - Performance related changes doc/guides/prog_guide/graph_lib.rst | 8 + lib/node/ethdev_ctrl.c | 13 ++ lib/node/ip6_rewrite.c | 331 ++++++++++++++++++++++++++++ lib/node/ip6_rewrite_priv.h | 69 ++++++ lib/node/meson.build | 1 + 5 files changed, 422 insertions(+) create mode 100644 lib/node/ip6_rewrite.c create mode 100644 lib/node/ip6_rewrite_priv.h diff --git a/doc/guides/prog_guide/graph_lib.rst b/doc/guides/prog_guide/graph_lib.rst index 1f70d63628..841cabe259 100644 --- a/doc/guides/prog_guide/graph_lib.rst +++ b/doc/guides/prog_guide/graph_lib.rst @@ -401,6 +401,14 @@ On LPM lookup failure, objects are redirected to pkt_drop node. To achieve home run, node use ``rte_node_stream_move()`` as mentioned in above sections. +ip6_rewrite +~~~~~~~~~~~ +This node gets packets from ``ip6_lookup`` node with next-hop id for each +packet is embedded in ``node_mbuf_priv1(mbuf)->nh``. This id is used +to determine the L2 header to be written to the packet before sending +the packet out to a particular ethdev_tx node. +``rte_node_ip6_rewrite_add()`` is control path API to add next-hop info. + null ~~~~ This node ignores the set of objects passed to it and reports that all are diff --git a/lib/node/ethdev_ctrl.c b/lib/node/ethdev_ctrl.c index 37df0431b8..ea7dc8210b 100644 --- a/lib/node/ethdev_ctrl.c +++ b/lib/node/ethdev_ctrl.c @@ -12,6 +12,7 @@ #include "ethdev_rx_priv.h" #include "ethdev_tx_priv.h" #include "ip4_rewrite_priv.h" +#include "ip6_rewrite_priv.h" #include "node_private.h" static struct ethdev_ctrl { @@ -23,6 +24,7 @@ rte_node_eth_config(struct rte_node_ethdev_config *conf, uint16_t nb_confs, uint16_t nb_graphs) { struct rte_node_register *ip4_rewrite_node; + struct rte_node_register *ip6_rewrite_node; struct ethdev_tx_node_main *tx_node_data; uint16_t tx_q_used, rx_q_used, port_id; struct rte_node_register *tx_node; @@ -33,6 +35,7 @@ rte_node_eth_config(struct rte_node_ethdev_config *conf, uint16_t nb_confs, uint32_t id; ip4_rewrite_node = ip4_rewrite_node_get(); + ip6_rewrite_node = ip6_rewrite_node_get(); tx_node_data = ethdev_tx_node_data_get(); tx_node = ethdev_tx_node_get(); for (i = 0; i < nb_confs; i++) { @@ -110,6 +113,16 @@ rte_node_eth_config(struct rte_node_ethdev_config *conf, uint16_t nb_confs, port_id, rte_node_edge_count(ip4_rewrite_node->id) - 1); if (rc < 0) return rc; + + /* Add this tx port node as next to ip6_rewrite_node */ + rte_node_edge_update(ip6_rewrite_node->id, RTE_EDGE_ID_INVALID, + &next_nodes, 1); + /* Assuming edge id is the last one alloc'ed */ + rc = ip6_rewrite_set_next( + port_id, rte_node_edge_count(ip6_rewrite_node->id) - 1); + if (rc < 0) + return rc; + } ctrl.nb_graphs = nb_graphs; diff --git a/lib/node/ip6_rewrite.c b/lib/node/ip6_rewrite.c new file mode 100644 index 0000000000..0e9631c86f --- /dev/null +++ b/lib/node/ip6_rewrite.c @@ -0,0 +1,331 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2023 Marvell. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "rte_node_ip6_api.h" + +#include "ip6_rewrite_priv.h" +#include "node_private.h" + +struct ip6_rewrite_node_ctx { + /* Dynamic offset to mbuf priv1 */ + int mbuf_priv1_off; + /* Cached next index */ + uint16_t next_index; +}; + +static struct ip6_rewrite_node_main *ip6_rewrite_nm; + +#define IP6_REWRITE_NODE_LAST_NEXT(ctx) \ + (((struct ip6_rewrite_node_ctx *)ctx)->next_index) + +#define IP6_REWRITE_NODE_PRIV1_OFF(ctx) \ + (((struct ip6_rewrite_node_ctx *)ctx)->mbuf_priv1_off) + +static uint16_t +ip6_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + struct rte_mbuf *mbuf0, *mbuf1, *mbuf2, *mbuf3, **pkts; + struct ip6_rewrite_nh_header *nh = ip6_rewrite_nm->nh; + const int dyn = IP6_REWRITE_NODE_PRIV1_OFF(node->ctx); + uint16_t next0, next1, next2, next3, next_index; + uint16_t n_left_from, held = 0, last_spec = 0; + struct rte_ipv6_hdr *ip0, *ip1, *ip2, *ip3; + void *d0, *d1, *d2, *d3; + void **to_next, **from; + rte_xmm_t priv01; + rte_xmm_t priv23; + int i; + + /* Speculative next as last next */ + next_index = IP6_REWRITE_NODE_LAST_NEXT(node->ctx); + rte_prefetch0(nh); + + pkts = (struct rte_mbuf **)objs; + from = objs; + n_left_from = nb_objs; + + for (i = 0; i < 4 && i < n_left_from; i++) + rte_prefetch0(pkts[i]); + + /* Get stream for the speculated next node */ + to_next = rte_node_next_stream_get(graph, node, next_index, nb_objs); + /* Update Ethernet header of pkts */ + while (n_left_from >= 4) { + if (likely(n_left_from > 7)) { + /* Prefetch only next-mbuf struct and priv area. + * Data need not be prefetched as we only write. + */ + rte_prefetch0(pkts[4]); + rte_prefetch0(pkts[5]); + rte_prefetch0(pkts[6]); + rte_prefetch0(pkts[7]); + } + + mbuf0 = pkts[0]; + mbuf1 = pkts[1]; + mbuf2 = pkts[2]; + mbuf3 = pkts[3]; + + pkts += 4; + n_left_from -= 4; + priv01.u64[0] = node_mbuf_priv1(mbuf0, dyn)->u; + priv01.u64[1] = node_mbuf_priv1(mbuf1, dyn)->u; + priv23.u64[0] = node_mbuf_priv1(mbuf2, dyn)->u; + priv23.u64[1] = node_mbuf_priv1(mbuf3, dyn)->u; + + /* Update next_hop rewrite ethernet hdr on mbuf0 */ + d0 = rte_pktmbuf_mtod(mbuf0, void *); + rte_memcpy(d0, nh[priv01.u16[0]].rewrite_data, + nh[priv01.u16[0]].rewrite_len); + + next0 = nh[priv01.u16[0]].tx_node; + ip0 = (struct rte_ipv6_hdr *)((uint8_t *)d0 + + sizeof(struct rte_ether_hdr)); + ip0->hop_limits = priv01.u16[1] - 1; + + /* Update next_hop rewrite ethernet hdr on mbuf1 */ + d1 = rte_pktmbuf_mtod(mbuf1, void *); + rte_memcpy(d1, nh[priv01.u16[4]].rewrite_data, + nh[priv01.u16[4]].rewrite_len); + + next1 = nh[priv01.u16[4]].tx_node; + ip1 = (struct rte_ipv6_hdr *)((uint8_t *)d1 + + sizeof(struct rte_ether_hdr)); + ip1->hop_limits = priv01.u16[5] - 1; + + /* Update next_hop rewrite ethernet hdr on mbuf2 */ + d2 = rte_pktmbuf_mtod(mbuf2, void *); + rte_memcpy(d2, nh[priv23.u16[0]].rewrite_data, + nh[priv23.u16[0]].rewrite_len); + next2 = nh[priv23.u16[0]].tx_node; + ip2 = (struct rte_ipv6_hdr *)((uint8_t *)d2 + + sizeof(struct rte_ether_hdr)); + ip2->hop_limits = priv23.u16[1] - 1; + + /* Update next_hop rewrite ethernet hdr on mbuf3 */ + d3 = rte_pktmbuf_mtod(mbuf3, void *); + rte_memcpy(d3, nh[priv23.u16[4]].rewrite_data, + nh[priv23.u16[4]].rewrite_len); + + next3 = nh[priv23.u16[4]].tx_node; + ip3 = (struct rte_ipv6_hdr *)((uint8_t *)d3 + + sizeof(struct rte_ether_hdr)); + ip3->hop_limits = priv23.u16[5] - 1; + + /* Enqueue four packets to next node */ + rte_edge_t fix_spec = + ((next_index == next0) && (next0 == next1) && + (next1 == next2) && (next2 == next3)); + + if (unlikely(fix_spec == 0)) { + /* 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; + + /* next0 */ + if (next_index == next0) { + to_next[0] = from[0]; + to_next++; + held++; + } else { + rte_node_enqueue_x1(graph, node, next0, + from[0]); + } + + /* next1 */ + if (next_index == next1) { + to_next[0] = from[1]; + to_next++; + held++; + } else { + rte_node_enqueue_x1(graph, node, next1, + from[1]); + } + + /* next2 */ + if (next_index == next2) { + to_next[0] = from[2]; + to_next++; + held++; + } else { + rte_node_enqueue_x1(graph, node, next2, + from[2]); + } + + /* next3 */ + if (next_index == next3) { + to_next[0] = from[3]; + to_next++; + held++; + } else { + rte_node_enqueue_x1(graph, node, next3, + from[3]); + } + + from += 4; + + /* Change speculation if last two are same */ + if ((next_index != next3) && (next2 == next3)) { + /* Put the current speculated node */ + rte_node_next_stream_put(graph, node, + next_index, held); + held = 0; + + /* Get next speculated stream */ + next_index = next3; + to_next = rte_node_next_stream_get( + graph, node, next_index, nb_objs); + } + } else { + last_spec += 4; + } + } + + while (n_left_from > 0) { + mbuf0 = pkts[0]; + + pkts += 1; + n_left_from -= 1; + + d0 = rte_pktmbuf_mtod(mbuf0, void *); + rte_memcpy(d0, nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_data, + nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_len); + + next0 = nh[node_mbuf_priv1(mbuf0, dyn)->nh].tx_node; + ip0 = (struct rte_ipv6_hdr *)((uint8_t *)d0 + + sizeof(struct rte_ether_hdr)); + ip0->hop_limits = node_mbuf_priv1(mbuf0, dyn)->ttl - 1; + + if (unlikely(next_index ^ next0)) { + /* 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, next0, 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 */ + IP6_REWRITE_NODE_LAST_NEXT(node->ctx) = next_index; + + return nb_objs; +} + +static int +ip6_rewrite_node_init(const struct rte_graph *graph, struct rte_node *node) +{ + static bool init_once; + + RTE_SET_USED(graph); + RTE_BUILD_BUG_ON(sizeof(struct ip6_rewrite_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; + init_once = true; + } + IP6_REWRITE_NODE_PRIV1_OFF(node->ctx) = ip6_node_mbuf_priv1_dynfield_offset; + + node_dbg("ip6_rewrite", "Initialized ip6_rewrite node"); + + return 0; +} + +int +ip6_rewrite_set_next(uint16_t port_id, uint16_t next_index) +{ + if (ip6_rewrite_nm == NULL) { + ip6_rewrite_nm = rte_zmalloc( + "ip6_rewrite", sizeof(struct ip6_rewrite_node_main), + RTE_CACHE_LINE_SIZE); + if (ip6_rewrite_nm == NULL) + return -ENOMEM; + } + ip6_rewrite_nm->next_index[port_id] = next_index; + + return 0; +} + +int +rte_node_ip6_rewrite_add(uint16_t next_hop, uint8_t *rewrite_data, + uint8_t rewrite_len, uint16_t dst_port) +{ + struct ip6_rewrite_nh_header *nh; + + if (next_hop >= RTE_GRAPH_IP6_REWRITE_MAX_NH) + return -EINVAL; + + if (rewrite_len > RTE_GRAPH_IP6_REWRITE_MAX_LEN) + return -EINVAL; + + if (ip6_rewrite_nm == NULL) { + ip6_rewrite_nm = rte_zmalloc( + "ip6_rewrite", sizeof(struct ip6_rewrite_node_main), + RTE_CACHE_LINE_SIZE); + if (ip6_rewrite_nm == NULL) + return -ENOMEM; + } + + /* Check if dst port doesn't exist as edge */ + if (!ip6_rewrite_nm->next_index[dst_port]) + return -EINVAL; + + /* Update next hop */ + nh = &ip6_rewrite_nm->nh[next_hop]; + + memcpy(nh->rewrite_data, rewrite_data, rewrite_len); + nh->tx_node = ip6_rewrite_nm->next_index[dst_port]; + nh->rewrite_len = rewrite_len; + nh->enabled = true; + + return 0; +} + +static struct rte_node_register ip6_rewrite_node = { + .process = ip6_rewrite_node_process, + .name = "ip6_rewrite", + /* Default edge i.e '0' is pkt drop */ + .nb_edges = 1, + .next_nodes = { + [0] = "pkt_drop", + }, + .init = ip6_rewrite_node_init, +}; + +struct rte_node_register * +ip6_rewrite_node_get(void) +{ + return &ip6_rewrite_node; +} + +RTE_NODE_REGISTER(ip6_rewrite_node); diff --git a/lib/node/ip6_rewrite_priv.h b/lib/node/ip6_rewrite_priv.h new file mode 100644 index 0000000000..93db28bec0 --- /dev/null +++ b/lib/node/ip6_rewrite_priv.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2023 Marvell. + */ +#ifndef __INCLUDE_IP6_REWRITE_PRIV_H__ +#define __INCLUDE_IP6_REWRITE_PRIV_H__ + +#include + +#define RTE_GRAPH_IP6_REWRITE_MAX_NH 64 +#define RTE_GRAPH_IP6_REWRITE_MAX_LEN 56 + +/** + * @internal + * + * Ipv6 rewrite next hop header data structure. Used to store port specific + * rewrite data. + */ +struct ip6_rewrite_nh_header { + uint16_t rewrite_len; /**< Header rewrite length. */ + uint16_t tx_node; /**< Tx node next index identifier. */ + uint16_t enabled; /**< NH enable flag */ + uint16_t rsvd; + union { + struct { + struct rte_ether_addr dst; + /**< Destination mac address. */ + struct rte_ether_addr src; + /**< Source mac address. */ + }; + uint8_t rewrite_data[RTE_GRAPH_IP6_REWRITE_MAX_LEN]; + /**< Generic rewrite data */ + }; +}; + +/** + * @internal + * + * Ipv6 node main data structure. + */ +struct ip6_rewrite_node_main { + struct ip6_rewrite_nh_header nh[RTE_GRAPH_IP6_REWRITE_MAX_NH]; + /**< Array of next hop header data */ + uint16_t next_index[RTE_MAX_ETHPORTS]; + /**< Next index of each configured port. */ +}; + +/** + * @internal + * + * Get the ipv6 rewrite node. + * + * @return + * Pointer to the ipv6 rewrite node. + */ +struct rte_node_register *ip6_rewrite_node_get(void); + +/** + * @internal + * + * Set the Edge index of a given port_id. + * + * @param port_id + * Ethernet port identifier. + * @param next_index + * Edge index of the Given Tx node. + */ +int ip6_rewrite_set_next(uint16_t port_id, uint16_t next_index); + +#endif /* __INCLUDE_IP6_REWRITE_PRIV_H__ */ diff --git a/lib/node/meson.build b/lib/node/meson.build index cd30847a0b..b2f04269c5 100644 --- a/lib/node/meson.build +++ b/lib/node/meson.build @@ -14,6 +14,7 @@ sources = files( 'ip4_lookup.c', 'ip6_lookup.c', 'ip4_rewrite.c', + 'ip6_rewrite.c', 'log.c', 'null.c', 'pkt_cls.c', From patchwork Thu May 18 15:56:54 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amit Prakash Shukla X-Patchwork-Id: 127022 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 5063A42AF1; Thu, 18 May 2023 17:57:18 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 51F9342D2D; Thu, 18 May 2023 17:57:14 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id ECCE842D3E for ; Thu, 18 May 2023 17:57:12 +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 34IAO6BR013340 for ; Thu, 18 May 2023 08:57:12 -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=uAvgVY68TgCixkbYg+0FIdysP9rr2IOOIKHOSg2Ihyw=; b=aWs3DT+PrzVbZfwD6d5o1asLnNalj+zmQPhPZl/eP6QOn0xiSOnOAaAZNkrYagtk1jwO 5mTP9oaeDXQa3J747NLjZDYK8pDtAeEVlBH/xgOswqNMvsPLZc4pwHQkgGPLfs7BnxPJ LpRUonJnuNdsygzs4sKiqOzEcRbeX1R5x6AXErxZMNTdxXGikgqNhRUaQv2GtytqY2it 3b1r1DSkINLa7HbclaEwI1wA/Wsn6ltzxwDlyKPl6u48N4liyFyHevI+GqSn3XXboQCo o+u1KCMp+LVqBytY1YzkvzfKvvCwKmSzYgfTEA9CUxxdzVcu8u1jQ8efQ5Q4YetCTPM5 ng== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3qn7jbbmya-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Thu, 18 May 2023 08:57:11 -0700 Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Thu, 18 May 2023 08:57:10 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Thu, 18 May 2023 08:57:10 -0700 Received: from localhost.localdomain (unknown [10.28.36.157]) by maili.marvell.com (Postfix) with ESMTP id 33D3A3F7043; Thu, 18 May 2023 08:57:07 -0700 (PDT) From: Amit Prakash Shukla To: Jerin Jacob , Kiran Kumar K , Nithin Dabilpuram CC: , , Amit Prakash Shukla Subject: [PATCH v2 3/3] examples/l3fwd-graph: add IPv6 lookup and rewrite support Date: Thu, 18 May 2023 21:26:54 +0530 Message-ID: <20230518155654.1756576-3-amitprakashs@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230518155654.1756576-1-amitprakashs@marvell.com> References: <20230516091157.1560829-1-amitprakashs@marvell.com> <20230518155654.1756576-1-amitprakashs@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: kBAQDlEHn_9vAQCNZm2lunbbHd88RGxF X-Proofpoint-ORIG-GUID: kBAQDlEHn_9vAQCNZm2lunbbHd88RGxF 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-18_12,2023-05-17_02,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, to support IPv6 lookup and rewrite node routes and rewrite data needs to be added. Patch adds routes for ipv6 to validate ip6_lookup node and rewrite data to validate ip6_rewrite node. Signed-off-by: Sunil Kumar Kori Signed-off-by: Amit Prakash Shukla --- v2: - Performance related changes doc/guides/sample_app_ug/l3_forward_graph.rst | 40 ++++++---- examples/l3fwd-graph/main.c | 77 ++++++++++++++++++- 2 files changed, 98 insertions(+), 19 deletions(-) diff --git a/doc/guides/sample_app_ug/l3_forward_graph.rst b/doc/guides/sample_app_ug/l3_forward_graph.rst index 585ac8c898..23f86e4785 100644 --- a/doc/guides/sample_app_ug/l3_forward_graph.rst +++ b/doc/guides/sample_app_ug/l3_forward_graph.rst @@ -12,7 +12,8 @@ Overview -------- The application demonstrates the use of the graph framework and graph nodes -``ethdev_rx``, ``ip4_lookup``, ``ip4_rewrite``, ``ethdev_tx`` and ``pkt_drop`` in DPDK to +``ethdev_rx``, ``pkt_cls``, ``ip4_lookup``/``ip6_lookup``, +``ip4_rewrite``/``ip6_rewrite``, ``ethdev_tx`` and ``pkt_drop`` in DPDK to implement packet forwarding. The initialization is very similar to those of the :doc:`l3_forward`. @@ -24,13 +25,15 @@ TTL update and finally Tx is implemented inside graph nodes. These nodes are interconnected in graph framework. Application main loop needs to walk over graph using ``rte_graph_walk()`` with graph objects created one per worker lcore. -The lookup method is as per implementation of ``ip4_lookup`` graph node. +The lookup method is as per implementation of ``ip4_lookup``/``ip6_lookup`` graph node. The ID of the output interface for the input packet is the next hop returned by the LPM lookup. The set of LPM rules used by the application is statically -configured and provided to ``ip4_lookup`` graph node and ``ip4_rewrite`` graph node -using node control API ``rte_node_ip4_route_add()`` and ``rte_node_ip4_rewrite_add()``. +configured and provided to ``ip4_lookup``/``ip6_lookup`` graph node and +``ip4_rewrite``/``ip6_rewrite`` graph node using node control API +``rte_node_ip4_route_add()``/``rte_node_ip6_route_add`` and +``rte_node_ip4_rewrite_add()``/``rte_node_ip6_rewrite_add``. -In the sample application, only IPv4 forwarding is supported as of now. +In the sample application, IPv4 and IPv6 forwarding is supported. Compiling the Application ------------------------- @@ -149,8 +152,8 @@ lead to the clone of ``ethdev_rx`` and ``ethdev_tx`` nodes as ``ethdev_rx-X-Y`` In case of ``ethdev_tx-X`` nodes, tx queue id assigned per instance of the node is same as graph id. -These cloned nodes along with existing static nodes such as ``ip4_lookup`` and -``ip4_rewrite`` will be used in graph creation to associate node's to lcore +These cloned nodes along with existing static nodes such as ``ip4_lookup``/``ip6_lookup`` +and ``ip4_rewrite``/``ip6_rewrite`` will be used in graph creation to associate node's to lcore specific graph object. .. literalinclude:: ../../../examples/l3fwd-graph/main.c @@ -186,20 +189,21 @@ Forwarding data(Route, Next-Hop) addition ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Once graph objects are created, node specific info like routes and rewrite -headers will be provided run-time using ``rte_node_ip4_route_add()`` and -``rte_node_ip4_rewrite_add()`` API. +headers will be provided run-time using ``rte_node_ip4_route_add()``/ +``rte_node_ip6_route_add`` and ``rte_node_ip4_rewrite_add()``/``rte_node_ip6_rewrite_add`` +API. .. note:: - Since currently ``ip4_lookup`` and ``ip4_rewrite`` nodes don't support - lock-less mechanisms(RCU, etc) to add run-time forwarding data like route and - rewrite data, forwarding data is added before packet processing loop is - launched on worker lcore. + Since currently ``ip4_lookup``/``ip6_lookup`` and ``ip4_rewrite``/``ip6_rewrite`` + nodes don't support lock-less mechanisms(RCU, etc) to add run-time forwarding + data like route and rewrite data, forwarding data is added before packet + processing loop is launched on worker lcore. .. literalinclude:: ../../../examples/l3fwd-graph/main.c :language: c - :start-after: Add route to ip4 graph infra. 8< - :end-before: >8 End of adding route to ip4 graph infa. + :start-after: Add routes and rewrite data to graph infra. 8< + :end-before: >8 End of adding routes and rewrite data to graph infa. :dedent: 1 Packet Forwarding using Graph Walk @@ -215,8 +219,10 @@ specific graph object that was already created. rte_graph_walk() will walk over all the sources nodes i.e ``ethdev_rx-X-Y`` associated with a given graph and Rx the available packets and enqueue them - to the following node ``ip4_lookup`` which then will enqueue them to ``ip4_rewrite`` - node if LPM lookup succeeds. ``ip4_rewrite`` node then will update Ethernet header + to the following node ``pkt_cls`` which based on the packet type will enqueue + them to ``ip4_lookup``/``ip6_lookup`` which then will enqueue them to + ``ip4_rewrite``/``ip6_rewrite`` node if LPM lookup succeeds. + ``ip4_rewrite``/``ip6_rewrite`` node then will update Ethernet header as per next-hop data and transmit the packet via port 'Z' by enqueuing to ``ethdev_tx-Z`` node instance in its graph object. diff --git a/examples/l3fwd-graph/main.c b/examples/l3fwd-graph/main.c index 5feeab4f0f..0c82e24513 100644 --- a/examples/l3fwd-graph/main.c +++ b/examples/l3fwd-graph/main.c @@ -27,9 +27,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -142,6 +144,12 @@ struct ipv4_l3fwd_lpm_route { uint8_t if_out; }; +struct ipv6_l3fwd_lpm_route { + uint8_t ip[RTE_LPM6_IPV6_ADDR_SIZE]; + uint8_t depth; + uint8_t if_out; +}; + #define IPV4_L3FWD_LPM_NUM_ROUTES \ (sizeof(ipv4_l3fwd_lpm_route_array) / \ sizeof(ipv4_l3fwd_lpm_route_array[0])) @@ -153,6 +161,28 @@ static struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = { {RTE_IPV4(198, 18, 6, 0), 24, 6}, {RTE_IPV4(198, 18, 7, 0), 24, 7}, }; +#define IPV6_L3FWD_LPM_NUM_ROUTES \ + (sizeof(ipv6_l3fwd_lpm_route_array) / \ + sizeof(ipv6_l3fwd_lpm_route_array[0])) +static struct ipv6_l3fwd_lpm_route ipv6_l3fwd_lpm_route_array[] = { + {{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00}, 48, 0}, + {{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01}, 48, 1}, + {{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02}, 48, 2}, + {{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03}, 48, 3}, + {{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04}, 48, 4}, + {{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05}, 48, 5}, + {{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06}, 48, 6}, + {{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02}, 48, 7}, +}; + static int check_lcore_params(void) { @@ -1128,7 +1158,7 @@ main(int argc, char **argv) memset(&rewrite_data, 0, sizeof(rewrite_data)); rewrite_len = sizeof(rewrite_data); - /* Add route to ip4 graph infra. 8< */ + /* Add routes and rewrite data to graph infra. 8< */ for (i = 0; i < IPV4_L3FWD_LPM_NUM_ROUTES; i++) { char route_str[INET6_ADDRSTRLEN * 4]; char abuf[INET6_ADDRSTRLEN]; @@ -1172,7 +1202,50 @@ main(int argc, char **argv) RTE_LOG(INFO, L3FWD_GRAPH, "Added route %s, next_hop %u\n", route_str, i); } - /* >8 End of adding route to ip4 graph infa. */ + + for (i = 0; i < IPV6_L3FWD_LPM_NUM_ROUTES; i++) { + char route_str[INET6_ADDRSTRLEN * 4]; + char abuf[INET6_ADDRSTRLEN]; + struct in6_addr in6; + uint32_t dst_port; + + /* Skip unused ports */ + if ((1 << ipv6_l3fwd_lpm_route_array[i].if_out & + enabled_port_mask) == 0) + continue; + + dst_port = ipv6_l3fwd_lpm_route_array[i].if_out; + + memcpy(in6.s6_addr, ipv6_l3fwd_lpm_route_array[i].ip, RTE_LPM6_IPV6_ADDR_SIZE); + snprintf(route_str, sizeof(route_str), "%s / %d (%d)", + inet_ntop(AF_INET6, &in6, abuf, sizeof(abuf)), + ipv6_l3fwd_lpm_route_array[i].depth, + ipv6_l3fwd_lpm_route_array[i].if_out); + + /* Use route index 'i' as next hop id */ + ret = rte_node_ip6_route_add(ipv6_l3fwd_lpm_route_array[i].ip, + ipv6_l3fwd_lpm_route_array[i].depth, i, + RTE_NODE_IP6_LOOKUP_NEXT_REWRITE); + + if (ret < 0) + rte_exit(EXIT_FAILURE, + "Unable to add ip6 route %s to graph\n", + route_str); + + memcpy(rewrite_data, val_eth + dst_port, rewrite_len); + + /* Add next hop rewrite data for id 'i' */ + ret = rte_node_ip6_rewrite_add(i, rewrite_data, + rewrite_len, dst_port); + if (ret < 0) + rte_exit(EXIT_FAILURE, + "Unable to add next hop %u for " + "route %s\n", i, route_str); + + RTE_LOG(INFO, L3FWD_GRAPH, "Added route %s, next_hop %u\n", + route_str, i); + } + /* >8 End of adding routes and rewrite data to graph infa. */ /* Launch per-lcore init on every worker lcore */ rte_eal_mp_remote_launch(graph_main_loop, NULL, SKIP_MAIN);