From patchwork Wed May 31 11:37:41 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: 127783 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 2983F42BF4; Wed, 31 May 2023 13:38:00 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 057B140ED7; Wed, 31 May 2023 13:38:00 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id E35CA40A82 for ; Wed, 31 May 2023 13:37:58 +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 34V80ZZv019356 for ; Wed, 31 May 2023 04:37:58 -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=FVP+8LDicjxlQu13pggMk8UBJGeJcbtVZQ6de9XnJLM=; b=InZtkm/9xUsCbhtx43tfhW3BvCh/LerPEcVOcCHkp+6L+Xwr3xZjDzeuiTtRt8ktVuP9 DaX9DXY4PdrApSO2FWqGTYkS8tgCsY0FxlwRIQMtjA41CNr+bvZen4AIfFaRfjHFXQD2 a3rZqio64zQyiPJAeyeawx8COIOE2jvl55LJMqchvc/qMxjF7qSFZpaLAraEq/soy/1i Xcch0bKyp1GT5lWDDTMZf1EBiE4gMTqcLMYhcPlv2Wwabx6IqkU0w97Af8sK/EdanmwQ lnlL0gAdX94i5vOnTk8D5qrdZH6xngtE26MXQcvAuLAaYOVKbRY6NN9lijegGt45BJcA Aw== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3qwsb8tud5-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Wed, 31 May 2023 04:37:55 -0700 Received: from DC5-EXCH02.marvell.com (10.69.176.39) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Wed, 31 May 2023 04:37:53 -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, 31 May 2023 04:37:53 -0700 Received: from localhost.localdomain (unknown [10.28.36.157]) by maili.marvell.com (Postfix) with ESMTP id D6A5B3F7075; Wed, 31 May 2023 04:37:50 -0700 (PDT) From: Amit Prakash Shukla To: Jerin Jacob , Kiran Kumar K , Nithin Dabilpuram , Pavan Nikhilesh CC: , , Amit Prakash Shukla Subject: [PATCH v3 1/3] lib: add IPv6 lookup node Date: Wed, 31 May 2023 17:07:41 +0530 Message-ID: <20230531113743.1929627-1-amitprakashs@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230518155654.1756576-1-amitprakashs@marvell.com> References: <20230518155654.1756576-1-amitprakashs@marvell.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: VT4dhXs3X3eLwj3YjejgCFaQgtCfqclS X-Proofpoint-GUID: VT4dhXs3X3eLwj3YjejgCFaQgtCfqclS X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.254,Aquarius:18.0.957,Hydra:6.0.573,FMLib:17.11.176.26 definitions=2023-05-31_07,2023-05-31_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 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 Acked-by: Nithin Dabilpuram --- v2: - Performance related changes v3: - Removing redundant dynamic variable doc/guides/prog_guide/graph_lib.rst | 13 + lib/node/ip6_lookup.c | 372 ++++++++++++++++++++++++++++ lib/node/meson.build | 3 +- lib/node/node_private.h | 2 +- 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, 485 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..e4bbc7ed67 --- /dev/null +++ b/lib/node/ip6_lookup.c @@ -0,0 +1,372 @@ +/* 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; +}; + +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) { + uint8_t ip_batch[4][16]; + int32_t next_hop[4]; + uint16_t next[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; + + /* 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) { + node_mbuf_priv1_dynfield_offset = + rte_mbuf_dynfield_register( + &node_mbuf_priv1_dynfield_desc); + if (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) = + 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..26135aaa5b 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; 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 Wed May 31 11:37:42 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: 127784 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 AC15942BF4; Wed, 31 May 2023 13:38:07 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 6F4A642D0D; Wed, 31 May 2023 13:38:04 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id 6EFB542D0B for ; Wed, 31 May 2023 13:38:01 +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 34V8RfTN019664 for ; Wed, 31 May 2023 04:38:00 -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=TRBDMh0BLGbbAzdDL+rIHmSG+cQLfRh7sYnLzQ8EzhM=; b=IvI6O/a4xLFX5YNjnpklSY4VW4hHtVZDH/Y9t3ulscXa+uudUk3LrqEaQYlNmXG/jwjk +kgV7LUfEEVXuIRWyxsCC2dZh3HIJfcrlvh68oWrPkNfUjsJ7Jw7/S4P2NYToJQIgI1v 9nQGhI5EClc5KpBxo3lBqVYhPnag/1SDHvyQbWRlJ380GprN+YcjDmZIn0GOUpl0Vx+L VI2bx+zPzAtdMmdHF/0GfjiVslj0EWpiftvsefdBia0pOGq10tvYc9ezMumy91LQ4g2A a+SSR7X0sv96YiCwkTaMRXl9HWt1qo9Um41/Nyv9w6ST46dCQKdXpigK04gDVBTG7YGu Dw== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3qwsb8tuda-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Wed, 31 May 2023 04:38:00 -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; Wed, 31 May 2023 04:37:57 -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; Wed, 31 May 2023 04:37:57 -0700 Received: from localhost.localdomain (unknown [10.28.36.157]) by maili.marvell.com (Postfix) with ESMTP id 14CA13F7075; Wed, 31 May 2023 04:37:54 -0700 (PDT) From: Amit Prakash Shukla To: Jerin Jacob , Kiran Kumar K , Nithin Dabilpuram , Pavan Nikhilesh CC: , , Amit Prakash Shukla Subject: [PATCH v3 2/3] lib: add IPv6 rewrite node Date: Wed, 31 May 2023 17:07:42 +0530 Message-ID: <20230531113743.1929627-2-amitprakashs@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230531113743.1929627-1-amitprakashs@marvell.com> References: <20230518155654.1756576-1-amitprakashs@marvell.com> <20230531113743.1929627-1-amitprakashs@marvell.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: p7rJpPLEJYvNKayc2rtC7PO5khHdcH3v X-Proofpoint-GUID: p7rJpPLEJYvNKayc2rtC7PO5khHdcH3v X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.254,Aquarius:18.0.957,Hydra:6.0.573,FMLib:17.11.176.26 definitions=2023-05-31_07,2023-05-31_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 Similar to IPv4 rewrite node, patch adds IPv6 rewrite node. Signed-off-by: Amit Prakash Shukla Acked-by: Nithin Dabilpuram --- v2: - Performance related changes v3: - Removing redundant dynamic variable 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..198d8d8820 --- /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) { + node_mbuf_priv1_dynfield_offset = rte_mbuf_dynfield_register( + &node_mbuf_priv1_dynfield_desc); + if (node_mbuf_priv1_dynfield_offset < 0) + return -rte_errno; + init_once = true; + } + IP6_REWRITE_NODE_PRIV1_OFF(node->ctx) = 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 Wed May 31 11:37:43 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: 127785 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 F07CC42BF4; Wed, 31 May 2023 13:38:13 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 7F00742B8C; Wed, 31 May 2023 13:38:08 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id 7AE6C42D17 for ; Wed, 31 May 2023 13:38: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 34V7r8T7020051 for ; Wed, 31 May 2023 04:38: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=6xECVM/3cI7elPTvcQuc98NmsAtboe0YDSxbW0+Wsb0=; b=Mo/aZ6vEORT8NutxtSux04dha+w5sD4Bns+VwjhVzi3hDXcZ/WgkBmm3Blg3XJ5dCzw3 hKB2/6seipbxbXbb4QNJrsBNInlm8Va8Y6oIdbmVj69T6cclpjvHXFE8Xshyzd56G3dM gxVN7YgDK8MEpX5YYqu99IRdLcvbYaERVBU4Pm1cNE06jEsXWPiy6+bY5tX1nVtujcdZ KVRpQwy1YtG8/xJAzOmY2/SzU1KZiMKlJs0Yy5mll/DU8Llw5np9e+lnA47YrDgvvaY0 ZFhf2/zv1MOUwyWQtxzWY5QSdZtgzOX2nRD7gCSKfw7ogRS4qB8UvMnLUX6JGJFGlxm6 /Q== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3qwsb8tude-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Wed, 31 May 2023 04:38:03 -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, 31 May 2023 04:38:01 -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, 31 May 2023 04:38:00 -0700 Received: from localhost.localdomain (unknown [10.28.36.157]) by maili.marvell.com (Postfix) with ESMTP id E9FBE3F707E; Wed, 31 May 2023 04:37:58 -0700 (PDT) From: Amit Prakash Shukla To: Jerin Jacob , Kiran Kumar K , Nithin Dabilpuram CC: , , Amit Prakash Shukla Subject: [PATCH v3 3/3] examples/l3fwd-graph: add IPv6 lookup and rewrite support Date: Wed, 31 May 2023 17:07:43 +0530 Message-ID: <20230531113743.1929627-3-amitprakashs@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230531113743.1929627-1-amitprakashs@marvell.com> References: <20230518155654.1756576-1-amitprakashs@marvell.com> <20230531113743.1929627-1-amitprakashs@marvell.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: dmjWgzDXzwTjLXvhhDIxBVBBAM8Tw52l X-Proofpoint-GUID: dmjWgzDXzwTjLXvhhDIxBVBBAM8Tw52l X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.254,Aquarius:18.0.957,Hydra:6.0.573,FMLib:17.11.176.26 definitions=2023-05-31_07,2023-05-31_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 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 Acked-by: Nithin Dabilpuram --- v2: - Performance related changes v3: - Removing redundant dynamic variable 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);