* [PATCH] node: add IPv4 reassembly node @ 2023-06-01 19:42 pbhagavatula 2023-06-02 16:48 ` [PATCH v2] " pbhagavatula 0 siblings, 1 reply; 7+ messages in thread From: pbhagavatula @ 2023-06-01 19:42 UTC (permalink / raw) To: jerinj, Kiran Kumar K, Nithin Dabilpuram, Pavan Nikhilesh; +Cc: dev From: Pavan Nikhilesh <pbhagavatula@marvell.com> Add IPv4 reassembly node. Signed-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com> --- Depends-on: series-28278 doc/guides/prog_guide/graph_lib.rst | 8 ++ lib/node/ethdev_rx.c | 1 + lib/node/ethdev_rx_priv.h | 1 + lib/node/ip4_reassembly.c | 175 ++++++++++++++++++++++++++++ lib/node/ip4_reassembly_priv.h | 28 +++++ lib/node/meson.build | 3 +- lib/node/rte_node_ip4_api.h | 35 ++++++ lib/node/version.map | 1 + 8 files changed, 251 insertions(+), 1 deletion(-) create mode 100644 lib/node/ip4_reassembly.c create mode 100644 lib/node/ip4_reassembly_priv.h diff --git a/doc/guides/prog_guide/graph_lib.rst b/doc/guides/prog_guide/graph_lib.rst index 841cabe259..49c470e287 100644 --- a/doc/guides/prog_guide/graph_lib.rst +++ b/doc/guides/prog_guide/graph_lib.rst @@ -388,6 +388,14 @@ 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. +ip4_reassembly +~~~~~~~~~~~~~~ +This node is an intermediate node that reassembles ipv4 fragmented packets, +non-fragmented packets pass through the node un-effected. The node rewrites +it's stream and moves it to the next node. +The fragment table and death row table should be setup via the +``rte_node_ip4_reassembly_configure`` API. + ip6_lookup ~~~~~~~~~~ This node is an intermediate node that does LPM lookup for the received diff --git a/lib/node/ethdev_rx.c b/lib/node/ethdev_rx.c index a19237b42f..6ed2e1834f 100644 --- a/lib/node/ethdev_rx.c +++ b/lib/node/ethdev_rx.c @@ -218,6 +218,7 @@ static struct rte_node_register ethdev_rx_node_base = { /* Default pkt classification node */ [ETHDEV_RX_NEXT_PKT_CLS] = "pkt_cls", [ETHDEV_RX_NEXT_IP4_LOOKUP] = "ip4_lookup", + [ETHDEV_RX_NEXT_IP4_REASSEMBLY] = "ip4_reassembly", }, }; diff --git a/lib/node/ethdev_rx_priv.h b/lib/node/ethdev_rx_priv.h index 7f24cf962e..574a76c2a6 100644 --- a/lib/node/ethdev_rx_priv.h +++ b/lib/node/ethdev_rx_priv.h @@ -39,6 +39,7 @@ struct ethdev_rx_node_elem { enum ethdev_rx_next_nodes { ETHDEV_RX_NEXT_IP4_LOOKUP, ETHDEV_RX_NEXT_PKT_CLS, + ETHDEV_RX_NEXT_IP4_REASSEMBLY, ETHDEV_RX_NEXT_MAX, }; diff --git a/lib/node/ip4_reassembly.c b/lib/node/ip4_reassembly.c new file mode 100644 index 0000000000..907db111c2 --- /dev/null +++ b/lib/node/ip4_reassembly.c @@ -0,0 +1,175 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2023 Marvell. + */ + +#include <arpa/inet.h> +#include <stdlib.h> +#include <sys/socket.h> + +#include <rte_cycles.h> +#include <rte_debug.h> +#include <rte_ethdev.h> +#include <rte_ether.h> +#include <rte_graph.h> +#include <rte_graph_worker.h> +#include <rte_ip.h> +#include <rte_ip_frag.h> +#include <rte_mbuf.h> +#include <rte_tcp.h> +#include <rte_udp.h> + +#include "rte_node_ip4_api.h" + +#include "ip4_reassembly_priv.h" +#include "node_private.h" + +struct ip4_reassembly_elem { + struct ip4_reassembly_elem *next; + struct ip4_reassembly_ctx ctx; + rte_node_t node_id; +}; + +/* IP4 reassembly global data struct */ +struct ip4_reassembly_node_main { + struct ip4_reassembly_elem *head; +}; + +typedef struct ip4_reassembly_ctx ip4_reassembly_ctx_t; +typedef struct ip4_reassembly_elem ip4_reassembly_elem_t; + +static struct ip4_reassembly_node_main ip4_reassembly_main; + +static uint16_t +ip4_reassembly_node_process(struct rte_graph *graph, struct rte_node *node, void **objs, + uint16_t nb_objs) +{ +#define PREFETCH_OFFSET 4 + struct rte_mbuf *mbuf, *mbuf_out; + struct rte_ip_frag_death_row *dr; + struct ip4_reassembly_ctx *ctx; + struct rte_ipv4_hdr *ipv4_hdr; + struct rte_ip_frag_tbl *tbl; + uint16_t idx = 0; + void **to_next; + int i; + + ctx = (struct ip4_reassembly_ctx *)node->ctx; + + /* Get core specific reassembly tbl */ + tbl = ctx->tbl; + dr = ctx->dr; + + for (i = 0; i < PREFETCH_OFFSET && i < nb_objs; i++) { + rte_prefetch0(rte_pktmbuf_mtod_offset((struct rte_mbuf *)objs[i], void *, + sizeof(struct rte_ether_hdr))); + } + + to_next = node->objs; + for (i = 0; i < nb_objs - PREFETCH_OFFSET; i++) { +#if RTE_GRAPH_BURST_SIZE > 64 + /* Prefetch next-next mbufs */ + if (likely(i + 8 < nb_objs)) + rte_prefetch0(objs[i + 8]); +#endif + rte_prefetch0(rte_pktmbuf_mtod_offset((struct rte_mbuf *)objs[i + PREFETCH_OFFSET], + void *, sizeof(struct rte_ether_hdr))); + mbuf = (struct rte_mbuf *)objs[i]; + + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr *, + sizeof(struct rte_ether_hdr)); + if (rte_ipv4_frag_pkt_is_fragmented(ipv4_hdr)) { + /* prepare mbuf: setup l2_len/l3_len. */ + mbuf->l2_len = sizeof(struct rte_ether_hdr); + mbuf->l3_len = sizeof(struct rte_ipv4_hdr); + + mbuf_out = rte_ipv4_frag_reassemble_packet(tbl, dr, mbuf, rte_rdtsc(), + ipv4_hdr); + } else { + mbuf_out = mbuf; + } + + if (mbuf_out) + to_next[idx++] = (void *)mbuf_out; + } + + for (; i < nb_objs; i++) { + mbuf = (struct rte_mbuf *)objs[i]; + + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr *, + sizeof(struct rte_ether_hdr)); + if (rte_ipv4_frag_pkt_is_fragmented(ipv4_hdr)) { + /* prepare mbuf: setup l2_len/l3_len. */ + mbuf->l2_len = sizeof(struct rte_ether_hdr); + mbuf->l3_len = sizeof(struct rte_ipv4_hdr); + + mbuf_out = rte_ipv4_frag_reassemble_packet(tbl, dr, mbuf, rte_rdtsc(), + ipv4_hdr); + } else { + mbuf_out = mbuf; + } + + if (mbuf_out) + to_next[idx++] = (void *)mbuf_out; + } + node->idx = idx; + rte_node_next_stream_move(graph, node, 0); + rte_ip_frag_free_death_row(dr, 4); + + return idx; +} + +int +rte_node_ip4_reassembly_configure(struct rte_node_ip4_reassembly_cfg *cfg, uint16_t cnt) +{ + ip4_reassembly_elem_t *elem; + int i; + + for (i = 0; i < cnt; i++) { + elem = malloc(sizeof(ip4_reassembly_elem_t)); + if (elem == NULL) + return -ENOMEM; + elem->ctx.dr = cfg[i].dr; + elem->ctx.tbl = cfg[i].tbl; + elem->node_id = cfg[i].node_id; + elem->next = ip4_reassembly_main.head; + ip4_reassembly_main.head = elem; + } + + return 0; +} + +static int +ip4_reassembly_node_init(const struct rte_graph *graph, struct rte_node *node) +{ + ip4_reassembly_ctx_t *ctx = (ip4_reassembly_ctx_t *)node->ctx; + ip4_reassembly_elem_t *elem = ip4_reassembly_main.head; + + RTE_SET_USED(graph); + while (elem) { + if (elem->node_id == node->id) { + /* Update node specific context */ + memcpy(ctx, &elem->ctx, sizeof(ip4_reassembly_ctx_t)); + break; + } + elem = elem->next; + } + + return 0; +} + +static struct rte_node_register ip4_reassembly_node = { + .process = ip4_reassembly_node_process, + .name = "ip4_reassembly", + + .init = ip4_reassembly_node_init, + + .nb_edges = RTE_NODE_IP4_REASSEMBLY_NEXT_MAX, +}; + +struct rte_node_register * +ip4_reassembly_node_get(void) +{ + return &ip4_reassembly_node; +} + +RTE_NODE_REGISTER(ip4_reassembly_node); diff --git a/lib/node/ip4_reassembly_priv.h b/lib/node/ip4_reassembly_priv.h new file mode 100644 index 0000000000..1fa70274ba --- /dev/null +++ b/lib/node/ip4_reassembly_priv.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2023 Marvell International Ltd. + */ + +#ifndef __INCLUDE_IP4_REASSEMBLY_PRIV_H__ +#define __INCLUDE_IP4_REASSEMBLY_PRIV_H__ + +/** + * @internal + * + * Ip4_reassembly context structure. + */ +struct ip4_reassembly_ctx { + struct rte_ip_frag_tbl *tbl; + struct rte_ip_frag_death_row *dr; +}; + +/** + * @internal + * + * Get the IP4 reassembly node + * + * @return + * Pointer to the IP4 reassembly node. + */ +struct rte_node_register *ip4_reassembly_node_get(void); + +#endif /* __INCLUDE_IP4_REASSEMBLY_PRIV_H__ */ diff --git a/lib/node/meson.build b/lib/node/meson.build index b2f04269c5..94d3f36163 100644 --- a/lib/node/meson.build +++ b/lib/node/meson.build @@ -19,8 +19,9 @@ sources = files( 'null.c', 'pkt_cls.c', 'pkt_drop.c', + 'ip4_reassembly.c' ) 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'] +deps += ['graph', 'mbuf', 'lpm', 'ethdev', 'mempool', 'cryptodev', 'ip_frag'] diff --git a/lib/node/rte_node_ip4_api.h b/lib/node/rte_node_ip4_api.h index 46d0d8976b..4d6561604b 100644 --- a/lib/node/rte_node_ip4_api.h +++ b/lib/node/rte_node_ip4_api.h @@ -35,6 +35,27 @@ enum rte_node_ip4_lookup_next { /**< Number of next nodes of lookup node. */ }; +/** + * IP4 reassembly next nodes. + */ +enum rte_node_ip4_reassembly_next { + RTE_NODE_IP4_REASSEMBLY_NEXT_MAX, + /**< Number of next nodes of reassembly node. */ +}; + +/** + * Reassembly configure structure. + * @see rte_node_ip4_reassembly_configure + */ +struct rte_node_ip4_reassembly_cfg { + struct rte_ip_frag_tbl *tbl; + /**< Reassembly fragmentation table. */ + struct rte_ip_frag_death_row *dr; + /**< Reassembly deathrow table. */ + rte_node_t node_id; + /**< Node identifier to configure. */ +}; + /** * Add ipv4 route to lookup table. * @@ -73,6 +94,20 @@ __rte_experimental int rte_node_ip4_rewrite_add(uint16_t next_hop, uint8_t *rewrite_data, uint8_t rewrite_len, uint16_t dst_port); +/** + * Add reassembly node configuration data. + * + * @param cfg + * Pointer to the configuration structure. + * @param cnt + * Number of configuration structures passed. + * + * @return + * 0 on success, negative otherwise. + */ +__rte_experimental +int rte_node_ip4_reassembly_configure(struct rte_node_ip4_reassembly_cfg *cfg, uint16_t cnt); + #ifdef __cplusplus } #endif diff --git a/lib/node/version.map b/lib/node/version.map index 40df308bfe..c10e2e78ea 100644 --- a/lib/node/version.map +++ b/lib/node/version.map @@ -4,6 +4,7 @@ EXPERIMENTAL { rte_node_eth_config; rte_node_ip4_route_add; rte_node_ip4_rewrite_add; + rte_node_ip4_reassembly_configure; rte_node_ip6_rewrite_add; rte_node_ip6_route_add; rte_node_logtype; -- 2.39.1 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2] node: add IPv4 reassembly node 2023-06-01 19:42 [PATCH] node: add IPv4 reassembly node pbhagavatula @ 2023-06-02 16:48 ` pbhagavatula 2023-06-05 11:26 ` [PATCH v3] node: add ipv4 " pbhagavatula 0 siblings, 1 reply; 7+ messages in thread From: pbhagavatula @ 2023-06-02 16:48 UTC (permalink / raw) To: jerinj, Kiran Kumar K, Nithin Dabilpuram, Pavan Nikhilesh; +Cc: dev From: Pavan Nikhilesh <pbhagavatula@marvell.com> Add IPv4 reassembly node. Signed-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com> --- Depends-on: series-28278 v2 Changes: - Fix compilation. doc/guides/prog_guide/graph_lib.rst | 8 ++ lib/node/ethdev_rx.c | 1 + lib/node/ethdev_rx_priv.h | 1 + lib/node/ip4_reassembly.c | 175 ++++++++++++++++++++++++++++ lib/node/ip4_reassembly_priv.h | 28 +++++ lib/node/meson.build | 3 +- lib/node/rte_node_ip4_api.h | 35 ++++++ lib/node/version.map | 1 + 8 files changed, 251 insertions(+), 1 deletion(-) create mode 100644 lib/node/ip4_reassembly.c create mode 100644 lib/node/ip4_reassembly_priv.h diff --git a/doc/guides/prog_guide/graph_lib.rst b/doc/guides/prog_guide/graph_lib.rst index 841cabe259..49c470e287 100644 --- a/doc/guides/prog_guide/graph_lib.rst +++ b/doc/guides/prog_guide/graph_lib.rst @@ -388,6 +388,14 @@ 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. +ip4_reassembly +~~~~~~~~~~~~~~ +This node is an intermediate node that reassembles ipv4 fragmented packets, +non-fragmented packets pass through the node un-effected. The node rewrites +it's stream and moves it to the next node. +The fragment table and death row table should be setup via the +``rte_node_ip4_reassembly_configure`` API. + ip6_lookup ~~~~~~~~~~ This node is an intermediate node that does LPM lookup for the received diff --git a/lib/node/ethdev_rx.c b/lib/node/ethdev_rx.c index a19237b42f..6ed2e1834f 100644 --- a/lib/node/ethdev_rx.c +++ b/lib/node/ethdev_rx.c @@ -218,6 +218,7 @@ static struct rte_node_register ethdev_rx_node_base = { /* Default pkt classification node */ [ETHDEV_RX_NEXT_PKT_CLS] = "pkt_cls", [ETHDEV_RX_NEXT_IP4_LOOKUP] = "ip4_lookup", + [ETHDEV_RX_NEXT_IP4_REASSEMBLY] = "ip4_reassembly", }, }; diff --git a/lib/node/ethdev_rx_priv.h b/lib/node/ethdev_rx_priv.h index 7f24cf962e..574a76c2a6 100644 --- a/lib/node/ethdev_rx_priv.h +++ b/lib/node/ethdev_rx_priv.h @@ -39,6 +39,7 @@ struct ethdev_rx_node_elem { enum ethdev_rx_next_nodes { ETHDEV_RX_NEXT_IP4_LOOKUP, ETHDEV_RX_NEXT_PKT_CLS, + ETHDEV_RX_NEXT_IP4_REASSEMBLY, ETHDEV_RX_NEXT_MAX, }; diff --git a/lib/node/ip4_reassembly.c b/lib/node/ip4_reassembly.c new file mode 100644 index 0000000000..907db111c2 --- /dev/null +++ b/lib/node/ip4_reassembly.c @@ -0,0 +1,175 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2023 Marvell. + */ + +#include <arpa/inet.h> +#include <stdlib.h> +#include <sys/socket.h> + +#include <rte_cycles.h> +#include <rte_debug.h> +#include <rte_ethdev.h> +#include <rte_ether.h> +#include <rte_graph.h> +#include <rte_graph_worker.h> +#include <rte_ip.h> +#include <rte_ip_frag.h> +#include <rte_mbuf.h> +#include <rte_tcp.h> +#include <rte_udp.h> + +#include "rte_node_ip4_api.h" + +#include "ip4_reassembly_priv.h" +#include "node_private.h" + +struct ip4_reassembly_elem { + struct ip4_reassembly_elem *next; + struct ip4_reassembly_ctx ctx; + rte_node_t node_id; +}; + +/* IP4 reassembly global data struct */ +struct ip4_reassembly_node_main { + struct ip4_reassembly_elem *head; +}; + +typedef struct ip4_reassembly_ctx ip4_reassembly_ctx_t; +typedef struct ip4_reassembly_elem ip4_reassembly_elem_t; + +static struct ip4_reassembly_node_main ip4_reassembly_main; + +static uint16_t +ip4_reassembly_node_process(struct rte_graph *graph, struct rte_node *node, void **objs, + uint16_t nb_objs) +{ +#define PREFETCH_OFFSET 4 + struct rte_mbuf *mbuf, *mbuf_out; + struct rte_ip_frag_death_row *dr; + struct ip4_reassembly_ctx *ctx; + struct rte_ipv4_hdr *ipv4_hdr; + struct rte_ip_frag_tbl *tbl; + uint16_t idx = 0; + void **to_next; + int i; + + ctx = (struct ip4_reassembly_ctx *)node->ctx; + + /* Get core specific reassembly tbl */ + tbl = ctx->tbl; + dr = ctx->dr; + + for (i = 0; i < PREFETCH_OFFSET && i < nb_objs; i++) { + rte_prefetch0(rte_pktmbuf_mtod_offset((struct rte_mbuf *)objs[i], void *, + sizeof(struct rte_ether_hdr))); + } + + to_next = node->objs; + for (i = 0; i < nb_objs - PREFETCH_OFFSET; i++) { +#if RTE_GRAPH_BURST_SIZE > 64 + /* Prefetch next-next mbufs */ + if (likely(i + 8 < nb_objs)) + rte_prefetch0(objs[i + 8]); +#endif + rte_prefetch0(rte_pktmbuf_mtod_offset((struct rte_mbuf *)objs[i + PREFETCH_OFFSET], + void *, sizeof(struct rte_ether_hdr))); + mbuf = (struct rte_mbuf *)objs[i]; + + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr *, + sizeof(struct rte_ether_hdr)); + if (rte_ipv4_frag_pkt_is_fragmented(ipv4_hdr)) { + /* prepare mbuf: setup l2_len/l3_len. */ + mbuf->l2_len = sizeof(struct rte_ether_hdr); + mbuf->l3_len = sizeof(struct rte_ipv4_hdr); + + mbuf_out = rte_ipv4_frag_reassemble_packet(tbl, dr, mbuf, rte_rdtsc(), + ipv4_hdr); + } else { + mbuf_out = mbuf; + } + + if (mbuf_out) + to_next[idx++] = (void *)mbuf_out; + } + + for (; i < nb_objs; i++) { + mbuf = (struct rte_mbuf *)objs[i]; + + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr *, + sizeof(struct rte_ether_hdr)); + if (rte_ipv4_frag_pkt_is_fragmented(ipv4_hdr)) { + /* prepare mbuf: setup l2_len/l3_len. */ + mbuf->l2_len = sizeof(struct rte_ether_hdr); + mbuf->l3_len = sizeof(struct rte_ipv4_hdr); + + mbuf_out = rte_ipv4_frag_reassemble_packet(tbl, dr, mbuf, rte_rdtsc(), + ipv4_hdr); + } else { + mbuf_out = mbuf; + } + + if (mbuf_out) + to_next[idx++] = (void *)mbuf_out; + } + node->idx = idx; + rte_node_next_stream_move(graph, node, 0); + rte_ip_frag_free_death_row(dr, 4); + + return idx; +} + +int +rte_node_ip4_reassembly_configure(struct rte_node_ip4_reassembly_cfg *cfg, uint16_t cnt) +{ + ip4_reassembly_elem_t *elem; + int i; + + for (i = 0; i < cnt; i++) { + elem = malloc(sizeof(ip4_reassembly_elem_t)); + if (elem == NULL) + return -ENOMEM; + elem->ctx.dr = cfg[i].dr; + elem->ctx.tbl = cfg[i].tbl; + elem->node_id = cfg[i].node_id; + elem->next = ip4_reassembly_main.head; + ip4_reassembly_main.head = elem; + } + + return 0; +} + +static int +ip4_reassembly_node_init(const struct rte_graph *graph, struct rte_node *node) +{ + ip4_reassembly_ctx_t *ctx = (ip4_reassembly_ctx_t *)node->ctx; + ip4_reassembly_elem_t *elem = ip4_reassembly_main.head; + + RTE_SET_USED(graph); + while (elem) { + if (elem->node_id == node->id) { + /* Update node specific context */ + memcpy(ctx, &elem->ctx, sizeof(ip4_reassembly_ctx_t)); + break; + } + elem = elem->next; + } + + return 0; +} + +static struct rte_node_register ip4_reassembly_node = { + .process = ip4_reassembly_node_process, + .name = "ip4_reassembly", + + .init = ip4_reassembly_node_init, + + .nb_edges = RTE_NODE_IP4_REASSEMBLY_NEXT_MAX, +}; + +struct rte_node_register * +ip4_reassembly_node_get(void) +{ + return &ip4_reassembly_node; +} + +RTE_NODE_REGISTER(ip4_reassembly_node); diff --git a/lib/node/ip4_reassembly_priv.h b/lib/node/ip4_reassembly_priv.h new file mode 100644 index 0000000000..1fa70274ba --- /dev/null +++ b/lib/node/ip4_reassembly_priv.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2023 Marvell International Ltd. + */ + +#ifndef __INCLUDE_IP4_REASSEMBLY_PRIV_H__ +#define __INCLUDE_IP4_REASSEMBLY_PRIV_H__ + +/** + * @internal + * + * Ip4_reassembly context structure. + */ +struct ip4_reassembly_ctx { + struct rte_ip_frag_tbl *tbl; + struct rte_ip_frag_death_row *dr; +}; + +/** + * @internal + * + * Get the IP4 reassembly node + * + * @return + * Pointer to the IP4 reassembly node. + */ +struct rte_node_register *ip4_reassembly_node_get(void); + +#endif /* __INCLUDE_IP4_REASSEMBLY_PRIV_H__ */ diff --git a/lib/node/meson.build b/lib/node/meson.build index b2f04269c5..94d3f36163 100644 --- a/lib/node/meson.build +++ b/lib/node/meson.build @@ -19,8 +19,9 @@ sources = files( 'null.c', 'pkt_cls.c', 'pkt_drop.c', + 'ip4_reassembly.c' ) 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'] +deps += ['graph', 'mbuf', 'lpm', 'ethdev', 'mempool', 'cryptodev', 'ip_frag'] diff --git a/lib/node/rte_node_ip4_api.h b/lib/node/rte_node_ip4_api.h index 46d0d8976b..4d6561604b 100644 --- a/lib/node/rte_node_ip4_api.h +++ b/lib/node/rte_node_ip4_api.h @@ -35,6 +35,27 @@ enum rte_node_ip4_lookup_next { /**< Number of next nodes of lookup node. */ }; +/** + * IP4 reassembly next nodes. + */ +enum rte_node_ip4_reassembly_next { + RTE_NODE_IP4_REASSEMBLY_NEXT_MAX, + /**< Number of next nodes of reassembly node. */ +}; + +/** + * Reassembly configure structure. + * @see rte_node_ip4_reassembly_configure + */ +struct rte_node_ip4_reassembly_cfg { + struct rte_ip_frag_tbl *tbl; + /**< Reassembly fragmentation table. */ + struct rte_ip_frag_death_row *dr; + /**< Reassembly deathrow table. */ + rte_node_t node_id; + /**< Node identifier to configure. */ +}; + /** * Add ipv4 route to lookup table. * @@ -73,6 +94,20 @@ __rte_experimental int rte_node_ip4_rewrite_add(uint16_t next_hop, uint8_t *rewrite_data, uint8_t rewrite_len, uint16_t dst_port); +/** + * Add reassembly node configuration data. + * + * @param cfg + * Pointer to the configuration structure. + * @param cnt + * Number of configuration structures passed. + * + * @return + * 0 on success, negative otherwise. + */ +__rte_experimental +int rte_node_ip4_reassembly_configure(struct rte_node_ip4_reassembly_cfg *cfg, uint16_t cnt); + #ifdef __cplusplus } #endif diff --git a/lib/node/version.map b/lib/node/version.map index 40df308bfe..c10e2e78ea 100644 --- a/lib/node/version.map +++ b/lib/node/version.map @@ -4,6 +4,7 @@ EXPERIMENTAL { rte_node_eth_config; rte_node_ip4_route_add; rte_node_ip4_rewrite_add; + rte_node_ip4_reassembly_configure; rte_node_ip6_rewrite_add; rte_node_ip6_route_add; rte_node_logtype; -- 2.39.1 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v3] node: add ipv4 reassembly node 2023-06-02 16:48 ` [PATCH v2] " pbhagavatula @ 2023-06-05 11:26 ` pbhagavatula 2023-06-06 6:14 ` Nithin Dabilpuram 2023-07-27 14:36 ` [PATCH v4] node: add IPv4 " pbhagavatula 0 siblings, 2 replies; 7+ messages in thread From: pbhagavatula @ 2023-06-05 11:26 UTC (permalink / raw) To: jerinj, Kiran Kumar K, Nithin Dabilpuram, Pavan Nikhilesh; +Cc: dev From: Pavan Nikhilesh <pbhagavatula@marvell.com> Add IPv4 reassembly node. Signed-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com> --- Depends-on: series-28278 v3 Changes: - Actually include the changes that fix compilation. v2 Changes: - Fix compilation. doc/guides/prog_guide/graph_lib.rst | 8 ++ lib/node/ethdev_rx.c | 1 + lib/node/ethdev_rx_priv.h | 1 + lib/node/ip4_reassembly.c | 175 ++++++++++++++++++++++++++++ lib/node/ip4_reassembly_priv.h | 28 +++++ lib/node/meson.build | 3 +- lib/node/rte_node_ip4_api.h | 37 ++++++ lib/node/version.map | 1 + 8 files changed, 253 insertions(+), 1 deletion(-) create mode 100644 lib/node/ip4_reassembly.c create mode 100644 lib/node/ip4_reassembly_priv.h diff --git a/doc/guides/prog_guide/graph_lib.rst b/doc/guides/prog_guide/graph_lib.rst index 841cabe259..49c470e287 100644 --- a/doc/guides/prog_guide/graph_lib.rst +++ b/doc/guides/prog_guide/graph_lib.rst @@ -388,6 +388,14 @@ 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. +ip4_reassembly +~~~~~~~~~~~~~~ +This node is an intermediate node that reassembles ipv4 fragmented packets, +non-fragmented packets pass through the node un-effected. The node rewrites +it's stream and moves it to the next node. +The fragment table and death row table should be setup via the +``rte_node_ip4_reassembly_configure`` API. + ip6_lookup ~~~~~~~~~~ This node is an intermediate node that does LPM lookup for the received diff --git a/lib/node/ethdev_rx.c b/lib/node/ethdev_rx.c index a19237b42f..6ed2e1834f 100644 --- a/lib/node/ethdev_rx.c +++ b/lib/node/ethdev_rx.c @@ -218,6 +218,7 @@ static struct rte_node_register ethdev_rx_node_base = { /* Default pkt classification node */ [ETHDEV_RX_NEXT_PKT_CLS] = "pkt_cls", [ETHDEV_RX_NEXT_IP4_LOOKUP] = "ip4_lookup", + [ETHDEV_RX_NEXT_IP4_REASSEMBLY] = "ip4_reassembly", }, }; diff --git a/lib/node/ethdev_rx_priv.h b/lib/node/ethdev_rx_priv.h index 7f24cf962e..574a76c2a6 100644 --- a/lib/node/ethdev_rx_priv.h +++ b/lib/node/ethdev_rx_priv.h @@ -39,6 +39,7 @@ struct ethdev_rx_node_elem { enum ethdev_rx_next_nodes { ETHDEV_RX_NEXT_IP4_LOOKUP, ETHDEV_RX_NEXT_PKT_CLS, + ETHDEV_RX_NEXT_IP4_REASSEMBLY, ETHDEV_RX_NEXT_MAX, }; diff --git a/lib/node/ip4_reassembly.c b/lib/node/ip4_reassembly.c new file mode 100644 index 0000000000..907db111c2 --- /dev/null +++ b/lib/node/ip4_reassembly.c @@ -0,0 +1,175 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2023 Marvell. + */ + +#include <arpa/inet.h> +#include <stdlib.h> +#include <sys/socket.h> + +#include <rte_cycles.h> +#include <rte_debug.h> +#include <rte_ethdev.h> +#include <rte_ether.h> +#include <rte_graph.h> +#include <rte_graph_worker.h> +#include <rte_ip.h> +#include <rte_ip_frag.h> +#include <rte_mbuf.h> +#include <rte_tcp.h> +#include <rte_udp.h> + +#include "rte_node_ip4_api.h" + +#include "ip4_reassembly_priv.h" +#include "node_private.h" + +struct ip4_reassembly_elem { + struct ip4_reassembly_elem *next; + struct ip4_reassembly_ctx ctx; + rte_node_t node_id; +}; + +/* IP4 reassembly global data struct */ +struct ip4_reassembly_node_main { + struct ip4_reassembly_elem *head; +}; + +typedef struct ip4_reassembly_ctx ip4_reassembly_ctx_t; +typedef struct ip4_reassembly_elem ip4_reassembly_elem_t; + +static struct ip4_reassembly_node_main ip4_reassembly_main; + +static uint16_t +ip4_reassembly_node_process(struct rte_graph *graph, struct rte_node *node, void **objs, + uint16_t nb_objs) +{ +#define PREFETCH_OFFSET 4 + struct rte_mbuf *mbuf, *mbuf_out; + struct rte_ip_frag_death_row *dr; + struct ip4_reassembly_ctx *ctx; + struct rte_ipv4_hdr *ipv4_hdr; + struct rte_ip_frag_tbl *tbl; + uint16_t idx = 0; + void **to_next; + int i; + + ctx = (struct ip4_reassembly_ctx *)node->ctx; + + /* Get core specific reassembly tbl */ + tbl = ctx->tbl; + dr = ctx->dr; + + for (i = 0; i < PREFETCH_OFFSET && i < nb_objs; i++) { + rte_prefetch0(rte_pktmbuf_mtod_offset((struct rte_mbuf *)objs[i], void *, + sizeof(struct rte_ether_hdr))); + } + + to_next = node->objs; + for (i = 0; i < nb_objs - PREFETCH_OFFSET; i++) { +#if RTE_GRAPH_BURST_SIZE > 64 + /* Prefetch next-next mbufs */ + if (likely(i + 8 < nb_objs)) + rte_prefetch0(objs[i + 8]); +#endif + rte_prefetch0(rte_pktmbuf_mtod_offset((struct rte_mbuf *)objs[i + PREFETCH_OFFSET], + void *, sizeof(struct rte_ether_hdr))); + mbuf = (struct rte_mbuf *)objs[i]; + + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr *, + sizeof(struct rte_ether_hdr)); + if (rte_ipv4_frag_pkt_is_fragmented(ipv4_hdr)) { + /* prepare mbuf: setup l2_len/l3_len. */ + mbuf->l2_len = sizeof(struct rte_ether_hdr); + mbuf->l3_len = sizeof(struct rte_ipv4_hdr); + + mbuf_out = rte_ipv4_frag_reassemble_packet(tbl, dr, mbuf, rte_rdtsc(), + ipv4_hdr); + } else { + mbuf_out = mbuf; + } + + if (mbuf_out) + to_next[idx++] = (void *)mbuf_out; + } + + for (; i < nb_objs; i++) { + mbuf = (struct rte_mbuf *)objs[i]; + + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr *, + sizeof(struct rte_ether_hdr)); + if (rte_ipv4_frag_pkt_is_fragmented(ipv4_hdr)) { + /* prepare mbuf: setup l2_len/l3_len. */ + mbuf->l2_len = sizeof(struct rte_ether_hdr); + mbuf->l3_len = sizeof(struct rte_ipv4_hdr); + + mbuf_out = rte_ipv4_frag_reassemble_packet(tbl, dr, mbuf, rte_rdtsc(), + ipv4_hdr); + } else { + mbuf_out = mbuf; + } + + if (mbuf_out) + to_next[idx++] = (void *)mbuf_out; + } + node->idx = idx; + rte_node_next_stream_move(graph, node, 0); + rte_ip_frag_free_death_row(dr, 4); + + return idx; +} + +int +rte_node_ip4_reassembly_configure(struct rte_node_ip4_reassembly_cfg *cfg, uint16_t cnt) +{ + ip4_reassembly_elem_t *elem; + int i; + + for (i = 0; i < cnt; i++) { + elem = malloc(sizeof(ip4_reassembly_elem_t)); + if (elem == NULL) + return -ENOMEM; + elem->ctx.dr = cfg[i].dr; + elem->ctx.tbl = cfg[i].tbl; + elem->node_id = cfg[i].node_id; + elem->next = ip4_reassembly_main.head; + ip4_reassembly_main.head = elem; + } + + return 0; +} + +static int +ip4_reassembly_node_init(const struct rte_graph *graph, struct rte_node *node) +{ + ip4_reassembly_ctx_t *ctx = (ip4_reassembly_ctx_t *)node->ctx; + ip4_reassembly_elem_t *elem = ip4_reassembly_main.head; + + RTE_SET_USED(graph); + while (elem) { + if (elem->node_id == node->id) { + /* Update node specific context */ + memcpy(ctx, &elem->ctx, sizeof(ip4_reassembly_ctx_t)); + break; + } + elem = elem->next; + } + + return 0; +} + +static struct rte_node_register ip4_reassembly_node = { + .process = ip4_reassembly_node_process, + .name = "ip4_reassembly", + + .init = ip4_reassembly_node_init, + + .nb_edges = RTE_NODE_IP4_REASSEMBLY_NEXT_MAX, +}; + +struct rte_node_register * +ip4_reassembly_node_get(void) +{ + return &ip4_reassembly_node; +} + +RTE_NODE_REGISTER(ip4_reassembly_node); diff --git a/lib/node/ip4_reassembly_priv.h b/lib/node/ip4_reassembly_priv.h new file mode 100644 index 0000000000..1fa70274ba --- /dev/null +++ b/lib/node/ip4_reassembly_priv.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2023 Marvell International Ltd. + */ + +#ifndef __INCLUDE_IP4_REASSEMBLY_PRIV_H__ +#define __INCLUDE_IP4_REASSEMBLY_PRIV_H__ + +/** + * @internal + * + * Ip4_reassembly context structure. + */ +struct ip4_reassembly_ctx { + struct rte_ip_frag_tbl *tbl; + struct rte_ip_frag_death_row *dr; +}; + +/** + * @internal + * + * Get the IP4 reassembly node + * + * @return + * Pointer to the IP4 reassembly node. + */ +struct rte_node_register *ip4_reassembly_node_get(void); + +#endif /* __INCLUDE_IP4_REASSEMBLY_PRIV_H__ */ diff --git a/lib/node/meson.build b/lib/node/meson.build index b2f04269c5..94d3f36163 100644 --- a/lib/node/meson.build +++ b/lib/node/meson.build @@ -19,8 +19,9 @@ sources = files( 'null.c', 'pkt_cls.c', 'pkt_drop.c', + 'ip4_reassembly.c' ) 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'] +deps += ['graph', 'mbuf', 'lpm', 'ethdev', 'mempool', 'cryptodev', 'ip_frag'] diff --git a/lib/node/rte_node_ip4_api.h b/lib/node/rte_node_ip4_api.h index 46d0d8976b..cec5c4e309 100644 --- a/lib/node/rte_node_ip4_api.h +++ b/lib/node/rte_node_ip4_api.h @@ -23,6 +23,8 @@ extern "C" { #include <rte_common.h> #include <rte_compat.h> +#include <rte_graph.h> + /** * IP4 lookup next nodes. */ @@ -35,6 +37,27 @@ enum rte_node_ip4_lookup_next { /**< Number of next nodes of lookup node. */ }; +/** + * IP4 reassembly next nodes. + */ +enum rte_node_ip4_reassembly_next { + RTE_NODE_IP4_REASSEMBLY_NEXT_MAX, + /**< Number of next nodes of reassembly node. */ +}; + +/** + * Reassembly configure structure. + * @see rte_node_ip4_reassembly_configure + */ +struct rte_node_ip4_reassembly_cfg { + struct rte_ip_frag_tbl *tbl; + /**< Reassembly fragmentation table. */ + struct rte_ip_frag_death_row *dr; + /**< Reassembly deathrow table. */ + rte_node_t node_id; + /**< Node identifier to configure. */ +}; + /** * Add ipv4 route to lookup table. * @@ -73,6 +96,20 @@ __rte_experimental int rte_node_ip4_rewrite_add(uint16_t next_hop, uint8_t *rewrite_data, uint8_t rewrite_len, uint16_t dst_port); +/** + * Add reassembly node configuration data. + * + * @param cfg + * Pointer to the configuration structure. + * @param cnt + * Number of configuration structures passed. + * + * @return + * 0 on success, negative otherwise. + */ +__rte_experimental +int rte_node_ip4_reassembly_configure(struct rte_node_ip4_reassembly_cfg *cfg, uint16_t cnt); + #ifdef __cplusplus } #endif diff --git a/lib/node/version.map b/lib/node/version.map index 40df308bfe..c10e2e78ea 100644 --- a/lib/node/version.map +++ b/lib/node/version.map @@ -4,6 +4,7 @@ EXPERIMENTAL { rte_node_eth_config; rte_node_ip4_route_add; rte_node_ip4_rewrite_add; + rte_node_ip4_reassembly_configure; rte_node_ip6_rewrite_add; rte_node_ip6_route_add; rte_node_logtype; -- 2.39.1 ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v3] node: add ipv4 reassembly node 2023-06-05 11:26 ` [PATCH v3] node: add ipv4 " pbhagavatula @ 2023-06-06 6:14 ` Nithin Dabilpuram 2023-07-27 14:36 ` [PATCH v4] node: add IPv4 " pbhagavatula 1 sibling, 0 replies; 7+ messages in thread From: Nithin Dabilpuram @ 2023-06-06 6:14 UTC (permalink / raw) To: pbhagavatula; +Cc: jerinj, Kiran Kumar K, Nithin Dabilpuram, dev On Mon, Jun 5, 2023 at 4:57 PM <pbhagavatula@marvell.com> wrote: > > From: Pavan Nikhilesh <pbhagavatula@marvell.com> > > Add IPv4 reassembly node. > > Signed-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com> > --- > Depends-on: series-28278 > > v3 Changes: > - Actually include the changes that fix compilation. > v2 Changes: > - Fix compilation. > > doc/guides/prog_guide/graph_lib.rst | 8 ++ > lib/node/ethdev_rx.c | 1 + > lib/node/ethdev_rx_priv.h | 1 + > lib/node/ip4_reassembly.c | 175 ++++++++++++++++++++++++++++ > lib/node/ip4_reassembly_priv.h | 28 +++++ > lib/node/meson.build | 3 +- > lib/node/rte_node_ip4_api.h | 37 ++++++ > lib/node/version.map | 1 + > 8 files changed, 253 insertions(+), 1 deletion(-) > create mode 100644 lib/node/ip4_reassembly.c > create mode 100644 lib/node/ip4_reassembly_priv.h > > diff --git a/doc/guides/prog_guide/graph_lib.rst b/doc/guides/prog_guide/graph_lib.rst > index 841cabe259..49c470e287 100644 > --- a/doc/guides/prog_guide/graph_lib.rst > +++ b/doc/guides/prog_guide/graph_lib.rst > @@ -388,6 +388,14 @@ 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. > > +ip4_reassembly > +~~~~~~~~~~~~~~ > +This node is an intermediate node that reassembles ipv4 fragmented packets, > +non-fragmented packets pass through the node un-effected. The node rewrites > +it's stream and moves it to the next node. > +The fragment table and death row table should be setup via the > +``rte_node_ip4_reassembly_configure`` API. > + > ip6_lookup > ~~~~~~~~~~ > This node is an intermediate node that does LPM lookup for the received > diff --git a/lib/node/ethdev_rx.c b/lib/node/ethdev_rx.c > index a19237b42f..6ed2e1834f 100644 > --- a/lib/node/ethdev_rx.c > +++ b/lib/node/ethdev_rx.c > @@ -218,6 +218,7 @@ static struct rte_node_register ethdev_rx_node_base = { > /* Default pkt classification node */ > [ETHDEV_RX_NEXT_PKT_CLS] = "pkt_cls", > [ETHDEV_RX_NEXT_IP4_LOOKUP] = "ip4_lookup", > + [ETHDEV_RX_NEXT_IP4_REASSEMBLY] = "ip4_reassembly", > }, > }; > > diff --git a/lib/node/ethdev_rx_priv.h b/lib/node/ethdev_rx_priv.h > index 7f24cf962e..574a76c2a6 100644 > --- a/lib/node/ethdev_rx_priv.h > +++ b/lib/node/ethdev_rx_priv.h > @@ -39,6 +39,7 @@ struct ethdev_rx_node_elem { > enum ethdev_rx_next_nodes { > ETHDEV_RX_NEXT_IP4_LOOKUP, > ETHDEV_RX_NEXT_PKT_CLS, > + ETHDEV_RX_NEXT_IP4_REASSEMBLY, > ETHDEV_RX_NEXT_MAX, > }; > > diff --git a/lib/node/ip4_reassembly.c b/lib/node/ip4_reassembly.c > new file mode 100644 > index 0000000000..907db111c2 > --- /dev/null > +++ b/lib/node/ip4_reassembly.c > @@ -0,0 +1,175 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(C) 2023 Marvell. > + */ > + > +#include <arpa/inet.h> > +#include <stdlib.h> > +#include <sys/socket.h> > + > +#include <rte_cycles.h> > +#include <rte_debug.h> > +#include <rte_ethdev.h> > +#include <rte_ether.h> > +#include <rte_graph.h> > +#include <rte_graph_worker.h> > +#include <rte_ip.h> > +#include <rte_ip_frag.h> > +#include <rte_mbuf.h> > +#include <rte_tcp.h> > +#include <rte_udp.h> > + > +#include "rte_node_ip4_api.h" > + > +#include "ip4_reassembly_priv.h" > +#include "node_private.h" > + > +struct ip4_reassembly_elem { > + struct ip4_reassembly_elem *next; > + struct ip4_reassembly_ctx ctx; > + rte_node_t node_id; > +}; > + > +/* IP4 reassembly global data struct */ > +struct ip4_reassembly_node_main { > + struct ip4_reassembly_elem *head; > +}; > + > +typedef struct ip4_reassembly_ctx ip4_reassembly_ctx_t; > +typedef struct ip4_reassembly_elem ip4_reassembly_elem_t; > + > +static struct ip4_reassembly_node_main ip4_reassembly_main; > + > +static uint16_t > +ip4_reassembly_node_process(struct rte_graph *graph, struct rte_node *node, void **objs, > + uint16_t nb_objs) > +{ > +#define PREFETCH_OFFSET 4 > + struct rte_mbuf *mbuf, *mbuf_out; > + struct rte_ip_frag_death_row *dr; > + struct ip4_reassembly_ctx *ctx; > + struct rte_ipv4_hdr *ipv4_hdr; > + struct rte_ip_frag_tbl *tbl; > + uint16_t idx = 0; > + void **to_next; > + int i; > + > + ctx = (struct ip4_reassembly_ctx *)node->ctx; > + > + /* Get core specific reassembly tbl */ > + tbl = ctx->tbl; > + dr = ctx->dr; > + > + for (i = 0; i < PREFETCH_OFFSET && i < nb_objs; i++) { > + rte_prefetch0(rte_pktmbuf_mtod_offset((struct rte_mbuf *)objs[i], void *, > + sizeof(struct rte_ether_hdr))); > + } > + > + to_next = node->objs; > + for (i = 0; i < nb_objs - PREFETCH_OFFSET; i++) { > +#if RTE_GRAPH_BURST_SIZE > 64 > + /* Prefetch next-next mbufs */ > + if (likely(i + 8 < nb_objs)) > + rte_prefetch0(objs[i + 8]); > +#endif > + rte_prefetch0(rte_pktmbuf_mtod_offset((struct rte_mbuf *)objs[i + PREFETCH_OFFSET], > + void *, sizeof(struct rte_ether_hdr))); > + mbuf = (struct rte_mbuf *)objs[i]; > + > + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr *, > + sizeof(struct rte_ether_hdr)); > + if (rte_ipv4_frag_pkt_is_fragmented(ipv4_hdr)) { > + /* prepare mbuf: setup l2_len/l3_len. */ > + mbuf->l2_len = sizeof(struct rte_ether_hdr); > + mbuf->l3_len = sizeof(struct rte_ipv4_hdr); > + > + mbuf_out = rte_ipv4_frag_reassemble_packet(tbl, dr, mbuf, rte_rdtsc(), > + ipv4_hdr); > + } else { > + mbuf_out = mbuf; > + } > + > + if (mbuf_out) > + to_next[idx++] = (void *)mbuf_out; > + } > + > + for (; i < nb_objs; i++) { > + mbuf = (struct rte_mbuf *)objs[i]; > + > + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr *, > + sizeof(struct rte_ether_hdr)); > + if (rte_ipv4_frag_pkt_is_fragmented(ipv4_hdr)) { > + /* prepare mbuf: setup l2_len/l3_len. */ > + mbuf->l2_len = sizeof(struct rte_ether_hdr); > + mbuf->l3_len = sizeof(struct rte_ipv4_hdr); > + > + mbuf_out = rte_ipv4_frag_reassemble_packet(tbl, dr, mbuf, rte_rdtsc(), > + ipv4_hdr); > + } else { > + mbuf_out = mbuf; > + } > + > + if (mbuf_out) > + to_next[idx++] = (void *)mbuf_out; > + } > + node->idx = idx; > + rte_node_next_stream_move(graph, node, 0); > + rte_ip_frag_free_death_row(dr, 4); Can these mbufs that are being freed sent to drop node so that it is tracked and accounted as dropped ? > + > + return idx; > +} > + > +int > +rte_node_ip4_reassembly_configure(struct rte_node_ip4_reassembly_cfg *cfg, uint16_t cnt) > +{ > + ip4_reassembly_elem_t *elem; > + int i; > + > + for (i = 0; i < cnt; i++) { > + elem = malloc(sizeof(ip4_reassembly_elem_t)); > + if (elem == NULL) > + return -ENOMEM; > + elem->ctx.dr = cfg[i].dr; > + elem->ctx.tbl = cfg[i].tbl; > + elem->node_id = cfg[i].node_id; > + elem->next = ip4_reassembly_main.head; > + ip4_reassembly_main.head = elem; > + } > + > + return 0; > +} > + > +static int > +ip4_reassembly_node_init(const struct rte_graph *graph, struct rte_node *node) > +{ > + ip4_reassembly_ctx_t *ctx = (ip4_reassembly_ctx_t *)node->ctx; > + ip4_reassembly_elem_t *elem = ip4_reassembly_main.head; > + > + RTE_SET_USED(graph); > + while (elem) { > + if (elem->node_id == node->id) { > + /* Update node specific context */ > + memcpy(ctx, &elem->ctx, sizeof(ip4_reassembly_ctx_t)); > + break; > + } > + elem = elem->next; > + } > + > + return 0; > +} > + > +static struct rte_node_register ip4_reassembly_node = { > + .process = ip4_reassembly_node_process, > + .name = "ip4_reassembly", > + > + .init = ip4_reassembly_node_init, > + > + .nb_edges = RTE_NODE_IP4_REASSEMBLY_NEXT_MAX, > +}; > + > +struct rte_node_register * > +ip4_reassembly_node_get(void) > +{ > + return &ip4_reassembly_node; > +} > + > +RTE_NODE_REGISTER(ip4_reassembly_node); > diff --git a/lib/node/ip4_reassembly_priv.h b/lib/node/ip4_reassembly_priv.h > new file mode 100644 > index 0000000000..1fa70274ba > --- /dev/null > +++ b/lib/node/ip4_reassembly_priv.h > @@ -0,0 +1,28 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(C) 2023 Marvell International Ltd. > + */ > + > +#ifndef __INCLUDE_IP4_REASSEMBLY_PRIV_H__ > +#define __INCLUDE_IP4_REASSEMBLY_PRIV_H__ > + > +/** > + * @internal > + * > + * Ip4_reassembly context structure. > + */ > +struct ip4_reassembly_ctx { > + struct rte_ip_frag_tbl *tbl; > + struct rte_ip_frag_death_row *dr; > +}; > + > +/** > + * @internal > + * > + * Get the IP4 reassembly node > + * > + * @return > + * Pointer to the IP4 reassembly node. > + */ > +struct rte_node_register *ip4_reassembly_node_get(void); > + > +#endif /* __INCLUDE_IP4_REASSEMBLY_PRIV_H__ */ > diff --git a/lib/node/meson.build b/lib/node/meson.build > index b2f04269c5..94d3f36163 100644 > --- a/lib/node/meson.build > +++ b/lib/node/meson.build > @@ -19,8 +19,9 @@ sources = files( > 'null.c', > 'pkt_cls.c', > 'pkt_drop.c', > + 'ip4_reassembly.c' > ) > 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'] > +deps += ['graph', 'mbuf', 'lpm', 'ethdev', 'mempool', 'cryptodev', 'ip_frag'] > diff --git a/lib/node/rte_node_ip4_api.h b/lib/node/rte_node_ip4_api.h > index 46d0d8976b..cec5c4e309 100644 > --- a/lib/node/rte_node_ip4_api.h > +++ b/lib/node/rte_node_ip4_api.h > @@ -23,6 +23,8 @@ extern "C" { > #include <rte_common.h> > #include <rte_compat.h> > > +#include <rte_graph.h> > + > /** > * IP4 lookup next nodes. > */ > @@ -35,6 +37,27 @@ enum rte_node_ip4_lookup_next { > /**< Number of next nodes of lookup node. */ > }; > > +/** > + * IP4 reassembly next nodes. > + */ > +enum rte_node_ip4_reassembly_next { > + RTE_NODE_IP4_REASSEMBLY_NEXT_MAX, > + /**< Number of next nodes of reassembly node. */ > +}; > + > +/** > + * Reassembly configure structure. > + * @see rte_node_ip4_reassembly_configure > + */ > +struct rte_node_ip4_reassembly_cfg { > + struct rte_ip_frag_tbl *tbl; > + /**< Reassembly fragmentation table. */ > + struct rte_ip_frag_death_row *dr; > + /**< Reassembly deathrow table. */ > + rte_node_t node_id; > + /**< Node identifier to configure. */ > +}; > + > /** > * Add ipv4 route to lookup table. > * > @@ -73,6 +96,20 @@ __rte_experimental > int rte_node_ip4_rewrite_add(uint16_t next_hop, uint8_t *rewrite_data, > uint8_t rewrite_len, uint16_t dst_port); > > +/** > + * Add reassembly node configuration data. > + * > + * @param cfg > + * Pointer to the configuration structure. > + * @param cnt > + * Number of configuration structures passed. > + * > + * @return > + * 0 on success, negative otherwise. > + */ > +__rte_experimental > +int rte_node_ip4_reassembly_configure(struct rte_node_ip4_reassembly_cfg *cfg, uint16_t cnt); > + > #ifdef __cplusplus > } > #endif > diff --git a/lib/node/version.map b/lib/node/version.map > index 40df308bfe..c10e2e78ea 100644 > --- a/lib/node/version.map > +++ b/lib/node/version.map > @@ -4,6 +4,7 @@ EXPERIMENTAL { > rte_node_eth_config; > rte_node_ip4_route_add; > rte_node_ip4_rewrite_add; > + rte_node_ip4_reassembly_configure; > rte_node_ip6_rewrite_add; > rte_node_ip6_route_add; > rte_node_logtype; > -- > 2.39.1 > ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v4] node: add IPv4 reassembly node 2023-06-05 11:26 ` [PATCH v3] node: add ipv4 " pbhagavatula 2023-06-06 6:14 ` Nithin Dabilpuram @ 2023-07-27 14:36 ` pbhagavatula 2023-09-08 5:37 ` Nithin Dabilpuram 1 sibling, 1 reply; 7+ messages in thread From: pbhagavatula @ 2023-07-27 14:36 UTC (permalink / raw) To: jerinj, ndabilpuram, Kiran Kumar K, Zhirun Yan, Pavan Nikhilesh; +Cc: dev From: Pavan Nikhilesh <pbhagavatula@marvell.com> Add IPv4 reassembly node. Signed-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com> --- v4 Changes: - Add packet drop node as the 0th edge. - Free deathrow packets to packet drop node. v3 Changes: - Actually include the changes that fix compilation. v2 Changes: - Fix compilation. doc/guides/prog_guide/graph_lib.rst | 8 ++ lib/node/ethdev_rx.c | 1 + lib/node/ethdev_rx_priv.h | 1 + lib/node/ip4_reassembly.c | 186 ++++++++++++++++++++++++++++ lib/node/ip4_reassembly_priv.h | 28 +++++ lib/node/meson.build | 3 +- lib/node/rte_node_ip4_api.h | 37 ++++++ lib/node/version.map | 1 + 8 files changed, 264 insertions(+), 1 deletion(-) create mode 100644 lib/node/ip4_reassembly.c create mode 100644 lib/node/ip4_reassembly_priv.h diff --git a/doc/guides/prog_guide/graph_lib.rst b/doc/guides/prog_guide/graph_lib.rst index e7b6e12004..10d146e2f6 100644 --- a/doc/guides/prog_guide/graph_lib.rst +++ b/doc/guides/prog_guide/graph_lib.rst @@ -453,6 +453,14 @@ 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. +ip4_reassembly +~~~~~~~~~~~~~~ +This node is an intermediate node that reassembles ipv4 fragmented packets, +non-fragmented packets pass through the node un-effected. The node rewrites +it's stream and moves it to the next node. +The fragment table and death row table should be setup via the +``rte_node_ip4_reassembly_configure`` API. + ip6_lookup ~~~~~~~~~~ This node is an intermediate node that does LPM lookup for the received diff --git a/lib/node/ethdev_rx.c b/lib/node/ethdev_rx.c index d131034991..3e8fac1df4 100644 --- a/lib/node/ethdev_rx.c +++ b/lib/node/ethdev_rx.c @@ -215,6 +215,7 @@ static struct rte_node_register ethdev_rx_node_base = { .next_nodes = { [ETHDEV_RX_NEXT_PKT_CLS] = "pkt_cls", [ETHDEV_RX_NEXT_IP4_LOOKUP] = "ip4_lookup", + [ETHDEV_RX_NEXT_IP4_REASSEMBLY] = "ip4_reassembly", }, }; diff --git a/lib/node/ethdev_rx_priv.h b/lib/node/ethdev_rx_priv.h index 7f24cf962e..574a76c2a6 100644 --- a/lib/node/ethdev_rx_priv.h +++ b/lib/node/ethdev_rx_priv.h @@ -39,6 +39,7 @@ struct ethdev_rx_node_elem { enum ethdev_rx_next_nodes { ETHDEV_RX_NEXT_IP4_LOOKUP, ETHDEV_RX_NEXT_PKT_CLS, + ETHDEV_RX_NEXT_IP4_REASSEMBLY, ETHDEV_RX_NEXT_MAX, }; diff --git a/lib/node/ip4_reassembly.c b/lib/node/ip4_reassembly.c new file mode 100644 index 0000000000..04823cc596 --- /dev/null +++ b/lib/node/ip4_reassembly.c @@ -0,0 +1,186 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2023 Marvell. + */ + +#include <arpa/inet.h> +#include <stdlib.h> +#include <sys/socket.h> + +#include <rte_cycles.h> +#include <rte_debug.h> +#include <rte_ethdev.h> +#include <rte_ether.h> +#include <rte_graph.h> +#include <rte_graph_worker.h> +#include <rte_ip.h> +#include <rte_ip_frag.h> +#include <rte_mbuf.h> +#include <rte_tcp.h> +#include <rte_udp.h> + +#include "rte_node_ip4_api.h" + +#include "ip4_reassembly_priv.h" +#include "node_private.h" + +struct ip4_reassembly_elem { + struct ip4_reassembly_elem *next; + struct ip4_reassembly_ctx ctx; + rte_node_t node_id; +}; + +/* IP4 reassembly global data struct */ +struct ip4_reassembly_node_main { + struct ip4_reassembly_elem *head; +}; + +typedef struct ip4_reassembly_ctx ip4_reassembly_ctx_t; +typedef struct ip4_reassembly_elem ip4_reassembly_elem_t; + +static struct ip4_reassembly_node_main ip4_reassembly_main; + +static uint16_t +ip4_reassembly_node_process(struct rte_graph *graph, struct rte_node *node, void **objs, + uint16_t nb_objs) +{ +#define PREFETCH_OFFSET 4 + struct rte_mbuf *mbuf, *mbuf_out; + struct rte_ip_frag_death_row *dr; + struct ip4_reassembly_ctx *ctx; + struct rte_ipv4_hdr *ipv4_hdr; + struct rte_ip_frag_tbl *tbl; + void **to_next, **to_free; + uint16_t idx = 0; + int i; + + ctx = (struct ip4_reassembly_ctx *)node->ctx; + + /* Get core specific reassembly tbl */ + tbl = ctx->tbl; + dr = ctx->dr; + + for (i = 0; i < PREFETCH_OFFSET && i < nb_objs; i++) { + rte_prefetch0(rte_pktmbuf_mtod_offset((struct rte_mbuf *)objs[i], void *, + sizeof(struct rte_ether_hdr))); + } + + to_next = node->objs; + for (i = 0; i < nb_objs - PREFETCH_OFFSET; i++) { +#if RTE_GRAPH_BURST_SIZE > 64 + /* Prefetch next-next mbufs */ + if (likely(i + 8 < nb_objs)) + rte_prefetch0(objs[i + 8]); +#endif + rte_prefetch0(rte_pktmbuf_mtod_offset((struct rte_mbuf *)objs[i + PREFETCH_OFFSET], + void *, sizeof(struct rte_ether_hdr))); + mbuf = (struct rte_mbuf *)objs[i]; + + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr *, + sizeof(struct rte_ether_hdr)); + if (rte_ipv4_frag_pkt_is_fragmented(ipv4_hdr)) { + /* prepare mbuf: setup l2_len/l3_len. */ + mbuf->l2_len = sizeof(struct rte_ether_hdr); + mbuf->l3_len = sizeof(struct rte_ipv4_hdr); + + mbuf_out = rte_ipv4_frag_reassemble_packet(tbl, dr, mbuf, rte_rdtsc(), + ipv4_hdr); + } else { + mbuf_out = mbuf; + } + + if (mbuf_out) + to_next[idx++] = (void *)mbuf_out; + } + + for (; i < nb_objs; i++) { + mbuf = (struct rte_mbuf *)objs[i]; + + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr *, + sizeof(struct rte_ether_hdr)); + if (rte_ipv4_frag_pkt_is_fragmented(ipv4_hdr)) { + /* prepare mbuf: setup l2_len/l3_len. */ + mbuf->l2_len = sizeof(struct rte_ether_hdr); + mbuf->l3_len = sizeof(struct rte_ipv4_hdr); + + mbuf_out = rte_ipv4_frag_reassemble_packet(tbl, dr, mbuf, rte_rdtsc(), + ipv4_hdr); + } else { + mbuf_out = mbuf; + } + + if (mbuf_out) + to_next[idx++] = (void *)mbuf_out; + } + node->idx = idx; + rte_node_next_stream_move(graph, node, 1); + if (dr->cnt) { + to_free = rte_node_next_stream_get(graph, node, + RTE_NODE_IP4_REASSEMBLY_NEXT_PKT_DROP, dr->cnt); + rte_memcpy(to_free, dr->row, dr->cnt * sizeof(to_free[0])); + rte_node_next_stream_put(graph, node, RTE_NODE_IP4_REASSEMBLY_NEXT_PKT_DROP, + dr->cnt); + idx += dr->cnt; + dr->cnt = 0; + } + + return idx; +} + +int +rte_node_ip4_reassembly_configure(struct rte_node_ip4_reassembly_cfg *cfg, uint16_t cnt) +{ + ip4_reassembly_elem_t *elem; + int i; + + for (i = 0; i < cnt; i++) { + elem = malloc(sizeof(ip4_reassembly_elem_t)); + if (elem == NULL) + return -ENOMEM; + elem->ctx.dr = cfg[i].dr; + elem->ctx.tbl = cfg[i].tbl; + elem->node_id = cfg[i].node_id; + elem->next = ip4_reassembly_main.head; + ip4_reassembly_main.head = elem; + } + + return 0; +} + +static int +ip4_reassembly_node_init(const struct rte_graph *graph, struct rte_node *node) +{ + ip4_reassembly_ctx_t *ctx = (ip4_reassembly_ctx_t *)node->ctx; + ip4_reassembly_elem_t *elem = ip4_reassembly_main.head; + + RTE_SET_USED(graph); + while (elem) { + if (elem->node_id == node->id) { + /* Update node specific context */ + memcpy(ctx, &elem->ctx, sizeof(ip4_reassembly_ctx_t)); + break; + } + elem = elem->next; + } + + return 0; +} + +static struct rte_node_register ip4_reassembly_node = { + .process = ip4_reassembly_node_process, + .name = "ip4_reassembly", + + .init = ip4_reassembly_node_init, + + .nb_edges = RTE_NODE_IP4_REASSEMBLY_NEXT_PKT_DROP + 1, + .next_nodes = { + [RTE_NODE_IP4_REASSEMBLY_NEXT_PKT_DROP] = "pkt_drop", + }, +}; + +struct rte_node_register * +ip4_reassembly_node_get(void) +{ + return &ip4_reassembly_node; +} + +RTE_NODE_REGISTER(ip4_reassembly_node); diff --git a/lib/node/ip4_reassembly_priv.h b/lib/node/ip4_reassembly_priv.h new file mode 100644 index 0000000000..1fa70274ba --- /dev/null +++ b/lib/node/ip4_reassembly_priv.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2023 Marvell International Ltd. + */ + +#ifndef __INCLUDE_IP4_REASSEMBLY_PRIV_H__ +#define __INCLUDE_IP4_REASSEMBLY_PRIV_H__ + +/** + * @internal + * + * Ip4_reassembly context structure. + */ +struct ip4_reassembly_ctx { + struct rte_ip_frag_tbl *tbl; + struct rte_ip_frag_death_row *dr; +}; + +/** + * @internal + * + * Get the IP4 reassembly node + * + * @return + * Pointer to the IP4 reassembly node. + */ +struct rte_node_register *ip4_reassembly_node_get(void); + +#endif /* __INCLUDE_IP4_REASSEMBLY_PRIV_H__ */ diff --git a/lib/node/meson.build b/lib/node/meson.build index 2fa7c1c8f3..72474c0856 100644 --- a/lib/node/meson.build +++ b/lib/node/meson.build @@ -13,6 +13,7 @@ sources = files( 'ethdev_tx.c', 'ip4_lookup.c', 'ip4_rewrite.c', + 'ip4_reassembly.c', 'ip6_lookup.c', 'ip6_rewrite.c', 'kernel_rx.c', @@ -30,4 +31,4 @@ headers = files( # Strict-aliasing rules are violated by uint8_t[] to context size casts. cflags += '-fno-strict-aliasing' -deps += ['graph', 'mbuf', 'lpm', 'ethdev', 'mempool', 'cryptodev'] +deps += ['graph', 'mbuf', 'lpm', 'ethdev', 'mempool', 'cryptodev', 'ip_frag'] diff --git a/lib/node/rte_node_ip4_api.h b/lib/node/rte_node_ip4_api.h index 3397da0ae8..8d8e4c41b2 100644 --- a/lib/node/rte_node_ip4_api.h +++ b/lib/node/rte_node_ip4_api.h @@ -22,6 +22,8 @@ extern "C" { #include <rte_common.h> #include <rte_compat.h> +#include <rte_graph.h> + /** * IP4 lookup next nodes. */ @@ -34,6 +36,27 @@ enum rte_node_ip4_lookup_next { /**< Number of next nodes of lookup node. */ }; +/** + * IP4 reassembly next nodes. + */ +enum rte_node_ip4_reassembly_next { + RTE_NODE_IP4_REASSEMBLY_NEXT_PKT_DROP, + /**< Packet drop node. */ +}; + +/** + * Reassembly configure structure. + * @see rte_node_ip4_reassembly_configure + */ +struct rte_node_ip4_reassembly_cfg { + struct rte_ip_frag_tbl *tbl; + /**< Reassembly fragmentation table. */ + struct rte_ip_frag_death_row *dr; + /**< Reassembly deathrow table. */ + rte_node_t node_id; + /**< Node identifier to configure. */ +}; + /** * Add ipv4 route to lookup table. * @@ -72,6 +95,20 @@ __rte_experimental int rte_node_ip4_rewrite_add(uint16_t next_hop, uint8_t *rewrite_data, uint8_t rewrite_len, uint16_t dst_port); +/** + * Add reassembly node configuration data. + * + * @param cfg + * Pointer to the configuration structure. + * @param cnt + * Number of configuration structures passed. + * + * @return + * 0 on success, negative otherwise. + */ +__rte_experimental +int rte_node_ip4_reassembly_configure(struct rte_node_ip4_reassembly_cfg *cfg, uint16_t cnt); + #ifdef __cplusplus } #endif diff --git a/lib/node/version.map b/lib/node/version.map index 40df308bfe..c10e2e78ea 100644 --- a/lib/node/version.map +++ b/lib/node/version.map @@ -4,6 +4,7 @@ EXPERIMENTAL { rte_node_eth_config; rte_node_ip4_route_add; rte_node_ip4_rewrite_add; + rte_node_ip4_reassembly_configure; rte_node_ip6_rewrite_add; rte_node_ip6_route_add; rte_node_logtype; -- 2.25.1 ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v4] node: add IPv4 reassembly node 2023-07-27 14:36 ` [PATCH v4] node: add IPv4 " pbhagavatula @ 2023-09-08 5:37 ` Nithin Dabilpuram 2023-10-17 11:16 ` Thomas Monjalon 0 siblings, 1 reply; 7+ messages in thread From: Nithin Dabilpuram @ 2023-09-08 5:37 UTC (permalink / raw) To: pbhagavatula; +Cc: jerinj, ndabilpuram, Kiran Kumar K, Zhirun Yan, dev Acked-by: Nithin Dabilpuram <ndabilpuram@marvell.com> On Thu, Jul 27, 2023 at 8:07 PM <pbhagavatula@marvell.com> wrote: > > From: Pavan Nikhilesh <pbhagavatula@marvell.com> > > Add IPv4 reassembly node. > > Signed-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com> > --- > v4 Changes: > - Add packet drop node as the 0th edge. > - Free deathrow packets to packet drop node. > v3 Changes: > - Actually include the changes that fix compilation. > v2 Changes: > - Fix compilation. > > doc/guides/prog_guide/graph_lib.rst | 8 ++ > lib/node/ethdev_rx.c | 1 + > lib/node/ethdev_rx_priv.h | 1 + > lib/node/ip4_reassembly.c | 186 ++++++++++++++++++++++++++++ > lib/node/ip4_reassembly_priv.h | 28 +++++ > lib/node/meson.build | 3 +- > lib/node/rte_node_ip4_api.h | 37 ++++++ > lib/node/version.map | 1 + > 8 files changed, 264 insertions(+), 1 deletion(-) > create mode 100644 lib/node/ip4_reassembly.c > create mode 100644 lib/node/ip4_reassembly_priv.h > > diff --git a/doc/guides/prog_guide/graph_lib.rst b/doc/guides/prog_guide/graph_lib.rst > index e7b6e12004..10d146e2f6 100644 > --- a/doc/guides/prog_guide/graph_lib.rst > +++ b/doc/guides/prog_guide/graph_lib.rst > @@ -453,6 +453,14 @@ 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. > > +ip4_reassembly > +~~~~~~~~~~~~~~ > +This node is an intermediate node that reassembles ipv4 fragmented packets, > +non-fragmented packets pass through the node un-effected. The node rewrites > +it's stream and moves it to the next node. > +The fragment table and death row table should be setup via the > +``rte_node_ip4_reassembly_configure`` API. > + > ip6_lookup > ~~~~~~~~~~ > This node is an intermediate node that does LPM lookup for the received > diff --git a/lib/node/ethdev_rx.c b/lib/node/ethdev_rx.c > index d131034991..3e8fac1df4 100644 > --- a/lib/node/ethdev_rx.c > +++ b/lib/node/ethdev_rx.c > @@ -215,6 +215,7 @@ static struct rte_node_register ethdev_rx_node_base = { > .next_nodes = { > [ETHDEV_RX_NEXT_PKT_CLS] = "pkt_cls", > [ETHDEV_RX_NEXT_IP4_LOOKUP] = "ip4_lookup", > + [ETHDEV_RX_NEXT_IP4_REASSEMBLY] = "ip4_reassembly", > }, > }; > > diff --git a/lib/node/ethdev_rx_priv.h b/lib/node/ethdev_rx_priv.h > index 7f24cf962e..574a76c2a6 100644 > --- a/lib/node/ethdev_rx_priv.h > +++ b/lib/node/ethdev_rx_priv.h > @@ -39,6 +39,7 @@ struct ethdev_rx_node_elem { > enum ethdev_rx_next_nodes { > ETHDEV_RX_NEXT_IP4_LOOKUP, > ETHDEV_RX_NEXT_PKT_CLS, > + ETHDEV_RX_NEXT_IP4_REASSEMBLY, > ETHDEV_RX_NEXT_MAX, > }; > > diff --git a/lib/node/ip4_reassembly.c b/lib/node/ip4_reassembly.c > new file mode 100644 > index 0000000000..04823cc596 > --- /dev/null > +++ b/lib/node/ip4_reassembly.c > @@ -0,0 +1,186 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(C) 2023 Marvell. > + */ > + > +#include <arpa/inet.h> > +#include <stdlib.h> > +#include <sys/socket.h> > + > +#include <rte_cycles.h> > +#include <rte_debug.h> > +#include <rte_ethdev.h> > +#include <rte_ether.h> > +#include <rte_graph.h> > +#include <rte_graph_worker.h> > +#include <rte_ip.h> > +#include <rte_ip_frag.h> > +#include <rte_mbuf.h> > +#include <rte_tcp.h> > +#include <rte_udp.h> > + > +#include "rte_node_ip4_api.h" > + > +#include "ip4_reassembly_priv.h" > +#include "node_private.h" > + > +struct ip4_reassembly_elem { > + struct ip4_reassembly_elem *next; > + struct ip4_reassembly_ctx ctx; > + rte_node_t node_id; > +}; > + > +/* IP4 reassembly global data struct */ > +struct ip4_reassembly_node_main { > + struct ip4_reassembly_elem *head; > +}; > + > +typedef struct ip4_reassembly_ctx ip4_reassembly_ctx_t; > +typedef struct ip4_reassembly_elem ip4_reassembly_elem_t; > + > +static struct ip4_reassembly_node_main ip4_reassembly_main; > + > +static uint16_t > +ip4_reassembly_node_process(struct rte_graph *graph, struct rte_node *node, void **objs, > + uint16_t nb_objs) > +{ > +#define PREFETCH_OFFSET 4 > + struct rte_mbuf *mbuf, *mbuf_out; > + struct rte_ip_frag_death_row *dr; > + struct ip4_reassembly_ctx *ctx; > + struct rte_ipv4_hdr *ipv4_hdr; > + struct rte_ip_frag_tbl *tbl; > + void **to_next, **to_free; > + uint16_t idx = 0; > + int i; > + > + ctx = (struct ip4_reassembly_ctx *)node->ctx; > + > + /* Get core specific reassembly tbl */ > + tbl = ctx->tbl; > + dr = ctx->dr; > + > + for (i = 0; i < PREFETCH_OFFSET && i < nb_objs; i++) { > + rte_prefetch0(rte_pktmbuf_mtod_offset((struct rte_mbuf *)objs[i], void *, > + sizeof(struct rte_ether_hdr))); > + } > + > + to_next = node->objs; > + for (i = 0; i < nb_objs - PREFETCH_OFFSET; i++) { > +#if RTE_GRAPH_BURST_SIZE > 64 > + /* Prefetch next-next mbufs */ > + if (likely(i + 8 < nb_objs)) > + rte_prefetch0(objs[i + 8]); > +#endif > + rte_prefetch0(rte_pktmbuf_mtod_offset((struct rte_mbuf *)objs[i + PREFETCH_OFFSET], > + void *, sizeof(struct rte_ether_hdr))); > + mbuf = (struct rte_mbuf *)objs[i]; > + > + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr *, > + sizeof(struct rte_ether_hdr)); > + if (rte_ipv4_frag_pkt_is_fragmented(ipv4_hdr)) { > + /* prepare mbuf: setup l2_len/l3_len. */ > + mbuf->l2_len = sizeof(struct rte_ether_hdr); > + mbuf->l3_len = sizeof(struct rte_ipv4_hdr); > + > + mbuf_out = rte_ipv4_frag_reassemble_packet(tbl, dr, mbuf, rte_rdtsc(), > + ipv4_hdr); > + } else { > + mbuf_out = mbuf; > + } > + > + if (mbuf_out) > + to_next[idx++] = (void *)mbuf_out; > + } > + > + for (; i < nb_objs; i++) { > + mbuf = (struct rte_mbuf *)objs[i]; > + > + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr *, > + sizeof(struct rte_ether_hdr)); > + if (rte_ipv4_frag_pkt_is_fragmented(ipv4_hdr)) { > + /* prepare mbuf: setup l2_len/l3_len. */ > + mbuf->l2_len = sizeof(struct rte_ether_hdr); > + mbuf->l3_len = sizeof(struct rte_ipv4_hdr); > + > + mbuf_out = rte_ipv4_frag_reassemble_packet(tbl, dr, mbuf, rte_rdtsc(), > + ipv4_hdr); > + } else { > + mbuf_out = mbuf; > + } > + > + if (mbuf_out) > + to_next[idx++] = (void *)mbuf_out; > + } > + node->idx = idx; > + rte_node_next_stream_move(graph, node, 1); > + if (dr->cnt) { > + to_free = rte_node_next_stream_get(graph, node, > + RTE_NODE_IP4_REASSEMBLY_NEXT_PKT_DROP, dr->cnt); > + rte_memcpy(to_free, dr->row, dr->cnt * sizeof(to_free[0])); > + rte_node_next_stream_put(graph, node, RTE_NODE_IP4_REASSEMBLY_NEXT_PKT_DROP, > + dr->cnt); > + idx += dr->cnt; > + dr->cnt = 0; > + } > + > + return idx; > +} > + > +int > +rte_node_ip4_reassembly_configure(struct rte_node_ip4_reassembly_cfg *cfg, uint16_t cnt) > +{ > + ip4_reassembly_elem_t *elem; > + int i; > + > + for (i = 0; i < cnt; i++) { > + elem = malloc(sizeof(ip4_reassembly_elem_t)); > + if (elem == NULL) > + return -ENOMEM; > + elem->ctx.dr = cfg[i].dr; > + elem->ctx.tbl = cfg[i].tbl; > + elem->node_id = cfg[i].node_id; > + elem->next = ip4_reassembly_main.head; > + ip4_reassembly_main.head = elem; > + } > + > + return 0; > +} > + > +static int > +ip4_reassembly_node_init(const struct rte_graph *graph, struct rte_node *node) > +{ > + ip4_reassembly_ctx_t *ctx = (ip4_reassembly_ctx_t *)node->ctx; > + ip4_reassembly_elem_t *elem = ip4_reassembly_main.head; > + > + RTE_SET_USED(graph); > + while (elem) { > + if (elem->node_id == node->id) { > + /* Update node specific context */ > + memcpy(ctx, &elem->ctx, sizeof(ip4_reassembly_ctx_t)); > + break; > + } > + elem = elem->next; > + } > + > + return 0; > +} > + > +static struct rte_node_register ip4_reassembly_node = { > + .process = ip4_reassembly_node_process, > + .name = "ip4_reassembly", > + > + .init = ip4_reassembly_node_init, > + > + .nb_edges = RTE_NODE_IP4_REASSEMBLY_NEXT_PKT_DROP + 1, > + .next_nodes = { > + [RTE_NODE_IP4_REASSEMBLY_NEXT_PKT_DROP] = "pkt_drop", > + }, > +}; > + > +struct rte_node_register * > +ip4_reassembly_node_get(void) > +{ > + return &ip4_reassembly_node; > +} > + > +RTE_NODE_REGISTER(ip4_reassembly_node); > diff --git a/lib/node/ip4_reassembly_priv.h b/lib/node/ip4_reassembly_priv.h > new file mode 100644 > index 0000000000..1fa70274ba > --- /dev/null > +++ b/lib/node/ip4_reassembly_priv.h > @@ -0,0 +1,28 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(C) 2023 Marvell International Ltd. > + */ > + > +#ifndef __INCLUDE_IP4_REASSEMBLY_PRIV_H__ > +#define __INCLUDE_IP4_REASSEMBLY_PRIV_H__ > + > +/** > + * @internal > + * > + * Ip4_reassembly context structure. > + */ > +struct ip4_reassembly_ctx { > + struct rte_ip_frag_tbl *tbl; > + struct rte_ip_frag_death_row *dr; > +}; > + > +/** > + * @internal > + * > + * Get the IP4 reassembly node > + * > + * @return > + * Pointer to the IP4 reassembly node. > + */ > +struct rte_node_register *ip4_reassembly_node_get(void); > + > +#endif /* __INCLUDE_IP4_REASSEMBLY_PRIV_H__ */ > diff --git a/lib/node/meson.build b/lib/node/meson.build > index 2fa7c1c8f3..72474c0856 100644 > --- a/lib/node/meson.build > +++ b/lib/node/meson.build > @@ -13,6 +13,7 @@ sources = files( > 'ethdev_tx.c', > 'ip4_lookup.c', > 'ip4_rewrite.c', > + 'ip4_reassembly.c', > 'ip6_lookup.c', > 'ip6_rewrite.c', > 'kernel_rx.c', > @@ -30,4 +31,4 @@ headers = files( > > # Strict-aliasing rules are violated by uint8_t[] to context size casts. > cflags += '-fno-strict-aliasing' > -deps += ['graph', 'mbuf', 'lpm', 'ethdev', 'mempool', 'cryptodev'] > +deps += ['graph', 'mbuf', 'lpm', 'ethdev', 'mempool', 'cryptodev', 'ip_frag'] > diff --git a/lib/node/rte_node_ip4_api.h b/lib/node/rte_node_ip4_api.h > index 3397da0ae8..8d8e4c41b2 100644 > --- a/lib/node/rte_node_ip4_api.h > +++ b/lib/node/rte_node_ip4_api.h > @@ -22,6 +22,8 @@ extern "C" { > #include <rte_common.h> > #include <rte_compat.h> > > +#include <rte_graph.h> > + > /** > * IP4 lookup next nodes. > */ > @@ -34,6 +36,27 @@ enum rte_node_ip4_lookup_next { > /**< Number of next nodes of lookup node. */ > }; > > +/** > + * IP4 reassembly next nodes. > + */ > +enum rte_node_ip4_reassembly_next { > + RTE_NODE_IP4_REASSEMBLY_NEXT_PKT_DROP, > + /**< Packet drop node. */ > +}; > + > +/** > + * Reassembly configure structure. > + * @see rte_node_ip4_reassembly_configure > + */ > +struct rte_node_ip4_reassembly_cfg { > + struct rte_ip_frag_tbl *tbl; > + /**< Reassembly fragmentation table. */ > + struct rte_ip_frag_death_row *dr; > + /**< Reassembly deathrow table. */ > + rte_node_t node_id; > + /**< Node identifier to configure. */ > +}; > + > /** > * Add ipv4 route to lookup table. > * > @@ -72,6 +95,20 @@ __rte_experimental > int rte_node_ip4_rewrite_add(uint16_t next_hop, uint8_t *rewrite_data, > uint8_t rewrite_len, uint16_t dst_port); > > +/** > + * Add reassembly node configuration data. > + * > + * @param cfg > + * Pointer to the configuration structure. > + * @param cnt > + * Number of configuration structures passed. > + * > + * @return > + * 0 on success, negative otherwise. > + */ > +__rte_experimental > +int rte_node_ip4_reassembly_configure(struct rte_node_ip4_reassembly_cfg *cfg, uint16_t cnt); > + > #ifdef __cplusplus > } > #endif > diff --git a/lib/node/version.map b/lib/node/version.map > index 40df308bfe..c10e2e78ea 100644 > --- a/lib/node/version.map > +++ b/lib/node/version.map > @@ -4,6 +4,7 @@ EXPERIMENTAL { > rte_node_eth_config; > rte_node_ip4_route_add; > rte_node_ip4_rewrite_add; > + rte_node_ip4_reassembly_configure; > rte_node_ip6_rewrite_add; > rte_node_ip6_route_add; > rte_node_logtype; > -- > 2.25.1 > ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v4] node: add IPv4 reassembly node 2023-09-08 5:37 ` Nithin Dabilpuram @ 2023-10-17 11:16 ` Thomas Monjalon 0 siblings, 0 replies; 7+ messages in thread From: Thomas Monjalon @ 2023-10-17 11:16 UTC (permalink / raw) To: pbhagavatula, dev Cc: jerinj, ndabilpuram, Kiran Kumar K, Zhirun Yan, dev, Nithin Dabilpuram 08/09/2023 07:37, Nithin Dabilpuram: > On Thu, Jul 27, 2023 at 8:07 PM <pbhagavatula@marvell.com> wrote: > > > > From: Pavan Nikhilesh <pbhagavatula@marvell.com> > > > > Add IPv4 reassembly node. > > > > Signed-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com> > Acked-by: Nithin Dabilpuram <ndabilpuram@marvell.com> [...] > > --- a/lib/node/meson.build > > +++ b/lib/node/meson.build > > @@ -13,6 +13,7 @@ sources = files( > > 'ethdev_tx.c', > > 'ip4_lookup.c', > > 'ip4_rewrite.c', > > + 'ip4_reassembly.c', > > 'ip6_lookup.c', > > 'ip6_rewrite.c', One space is missing here. Applied with space fixed, thanks. ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2023-10-17 11:16 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2023-06-01 19:42 [PATCH] node: add IPv4 reassembly node pbhagavatula 2023-06-02 16:48 ` [PATCH v2] " pbhagavatula 2023-06-05 11:26 ` [PATCH v3] node: add ipv4 " pbhagavatula 2023-06-06 6:14 ` Nithin Dabilpuram 2023-07-27 14:36 ` [PATCH v4] node: add IPv4 " pbhagavatula 2023-09-08 5:37 ` Nithin Dabilpuram 2023-10-17 11:16 ` Thomas Monjalon
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).