From 0555f11c2e0fe2a6b6da7778670d326ee4eb4f7d Mon Sep 17 00:00:00 2001 From: Pavan Nikhilesh Date: Sat, 11 Apr 2020 19:44:18 +0530 Subject: [PATCH] node: add generic IPv4 lookup Add IPv4 lookup process function for ip4_lookup node. This node performs LPM lookup using simple RTE_LPM API on every packet received and forwards it to a next node that is identified by lookup result. Signed-off-by: Pavan Nikhilesh Signed-off-by: Nithin Dabilpuram --- doc/api/doxy-api-index.md | 1 + lib/librte_node/Makefile | 4 +- lib/librte_node/ip4_lookup.c | 128 +++++++++++++++++++++++++++++ lib/librte_node/meson.build | 5 +- lib/librte_node/rte_node_ip4_api.h | 40 +++++++++ 5 files changed, 175 insertions(+), 3 deletions(-) create mode 100644 lib/librte_node/ip4_lookup.c create mode 100644 lib/librte_node/rte_node_ip4_api.h diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index a4d57a51fe..93f0d933b1 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -163,6 +163,7 @@ The public API headers are grouped by topics: [graph_worker] (@ref rte_graph_worker.h) * graph_nodes: [eth_node] (@ref rte_node_eth_api.h), + [ip4_node] (@ref rte_node_ip4_api.h) - **basic**: [approx fraction] (@ref rte_approx.h), diff --git a/lib/librte_node/Makefile b/lib/librte_node/Makefile index 3ce1fa6200..f5ac147fe1 100644 --- a/lib/librte_node/Makefile +++ b/lib/librte_node/Makefile @@ -11,7 +11,7 @@ CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) # Strict-aliasing rules are violated by uint8_t[] to context size casts. CFLAGS += -fno-strict-aliasing -LDLIBS += -lrte_eal -lrte_graph -lrte_mbuf -lrte_ethdev -lrte_mempool +LDLIBS += -lrte_eal -lrte_graph -lrte_mbuf -lrte_lpm -lrte_ethdev -lrte_mempool EXPORT_MAP := rte_node_version.map @@ -21,8 +21,10 @@ SRCS-$(CONFIG_RTE_LIBRTE_NODE) += log.c SRCS-$(CONFIG_RTE_LIBRTE_NODE) += ethdev_rx.c SRCS-$(CONFIG_RTE_LIBRTE_NODE) += ethdev_tx.c SRCS-$(CONFIG_RTE_LIBRTE_NODE) += ethdev_ctrl.c +SRCS-$(CONFIG_RTE_LIBRTE_NODE) += ip4_lookup.c # install header files +SYMLINK-$(CONFIG_RTE_LIBRTE_NODE)-include += rte_node_ip4_api.h SYMLINK-$(CONFIG_RTE_LIBRTE_NODE)-include += rte_node_eth_api.h include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_node/ip4_lookup.c b/lib/librte_node/ip4_lookup.c new file mode 100644 index 0000000000..988bc5e0cd --- /dev/null +++ b/lib/librte_node/ip4_lookup.c @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2020 Marvell International Ltd. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rte_node_ip4_api.h" + +#include "node_private.h" + +#define IPV4_L3FWD_LPM_MAX_RULES 1024 +#define IPV4_L3FWD_LPM_NUMBER_TBL8S (1 << 8) + +/* IP4 Lookup global data struct */ +struct ip4_lookup_node_main { + struct rte_lpm *lpm_tbl[RTE_MAX_NUMA_NODES]; +}; + +static uint16_t +ip4_lookup_node_process(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + struct rte_ipv4_hdr *ipv4_hdr; + void **to_next, **from; + uint16_t last_spec = 0; + struct rte_mbuf *mbuf; + rte_edge_t next_index; + struct rte_lpm *lpm; + uint16_t held = 0; + uint32_t drop_nh; + int i, rc; + + /* Speculative next */ + next_index = RTE_NODE_IP4_LOOKUP_NEXT_REWRITE; + /* Drop node */ + drop_nh = ((uint32_t)RTE_NODE_IP4_LOOKUP_NEXT_PKT_DROP) << 16; + + /* Get socket specific LPM from ctx */ + lpm = *((struct rte_lpm **)node->ctx); + from = objs; + + /* Get stream for the speculated next node */ + to_next = rte_node_next_stream_get(graph, node, next_index, nb_objs); + for (i = 0; i < nb_objs; i++) { + uint32_t next_hop; + uint16_t next; + + mbuf = (struct rte_mbuf *)objs[i]; + + /* Extract DIP of mbuf0 */ + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr *, + sizeof(struct rte_ether_hdr)); + /* Extract cksum, ttl as ipv4 hdr is in cache */ + node_mbuf_priv1(mbuf)->cksum = ipv4_hdr->hdr_checksum; + node_mbuf_priv1(mbuf)->ttl = ipv4_hdr->time_to_live; + + rc = rte_lpm_lookup(lpm, rte_be_to_cpu_32(ipv4_hdr->dst_addr), + &next_hop); + next_hop = (rc == 0) ? next_hop : drop_nh; + + node_mbuf_priv1(mbuf)->nh = (uint16_t)next_hop; + next_hop = next_hop >> 16; + next = (uint16_t)next_hop; + + if (unlikely(next_index != next)) { + /* Copy things successfully speculated till now */ + rte_memcpy(to_next, from, last_spec * sizeof(from[0])); + from += last_spec; + to_next += last_spec; + held += last_spec; + last_spec = 0; + + rte_node_enqueue_x1(graph, node, next, from[0]); + from += 1; + } else { + last_spec += 1; + } + } + + /* !!! Home run !!! */ + if (likely(last_spec == nb_objs)) { + rte_node_next_stream_move(graph, node, next_index); + return nb_objs; + } + held += last_spec; + rte_memcpy(to_next, from, last_spec * sizeof(from[0])); + rte_node_next_stream_put(graph, node, next_index, held); + + return nb_objs; +} + +static int +ip4_lookup_node_init(const struct rte_graph *graph, struct rte_node *node) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + + node_dbg("ip4_lookup", "Initialized ip4_lookup node"); + + return 0; +} + +static struct rte_node_register ip4_lookup_node = { + .process = ip4_lookup_node_process, + .name = "ip4_lookup", + + .init = ip4_lookup_node_init, + + .nb_edges = RTE_NODE_IP4_LOOKUP_NEXT_MAX, + .next_nodes = { + [RTE_NODE_IP4_LOOKUP_NEXT_REWRITE] = "ip4_rewrite", + [RTE_NODE_IP4_LOOKUP_NEXT_PKT_DROP] = "pkt_drop", + }, +}; + +RTE_NODE_REGISTER(ip4_lookup_node); diff --git a/lib/librte_node/meson.build b/lib/librte_node/meson.build index 0361f8f24a..e2e1b03fc2 100644 --- a/lib/librte_node/meson.build +++ b/lib/librte_node/meson.build @@ -1,8 +1,9 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(C) 2020 Marvell International Ltd. -sources = files('null.c', 'log.c', 'ethdev_rx.c', 'ethdev_tx.c', 'ethdev_ctrl.c') -headers = files('rte_node_eth_api.h') +sources = files('null.c', 'log.c', 'ethdev_rx.c', 'ethdev_tx.c', 'ip4_lookup.c', + 'ethdev_ctrl.c') +headers = files('rte_node_ip4_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/librte_node/rte_node_ip4_api.h b/lib/librte_node/rte_node_ip4_api.h new file mode 100644 index 0000000000..0b9ba48a20 --- /dev/null +++ b/lib/librte_node/rte_node_ip4_api.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2020 Marvell International Ltd. + */ + +#ifndef __INCLUDE_RTE_NODE_IP4_API_H__ +#define __INCLUDE_RTE_NODE_IP4_API_H__ + +/** + * @file rte_node_ip4_api.h + * + * @warning + * @b EXPERIMENTAL: this API may change without prior notice + * + * This API allows to do control path functions of ip4_* nodes + * like ip4_lookup, ip4_rewrite. + * + */ +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/** + * IP4 lookup next nodes. + */ +enum rte_node_ip4_lookup_next { + RTE_NODE_IP4_LOOKUP_NEXT_REWRITE, + /**< Rewrite node. */ + RTE_NODE_IP4_LOOKUP_NEXT_PKT_DROP, + /**< Packet drop node. */ + RTE_NODE_IP4_LOOKUP_NEXT_MAX, + /**< Number of next nodes of lookup node. */ +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_RTE_NODE_IP4_API_H__ */ -- 2.20.1