xref: /dpdk/lib/node/ip4_reassembly.c (revision be4c0cb4901fc0703786e0d3da4e0123306e4539)
10124e18fSPavan Nikhilesh /* SPDX-License-Identifier: BSD-3-Clause
20124e18fSPavan Nikhilesh  * Copyright(C) 2023 Marvell.
30124e18fSPavan Nikhilesh  */
40124e18fSPavan Nikhilesh 
50124e18fSPavan Nikhilesh #include <arpa/inet.h>
60124e18fSPavan Nikhilesh #include <stdlib.h>
70124e18fSPavan Nikhilesh #include <sys/socket.h>
80124e18fSPavan Nikhilesh 
90124e18fSPavan Nikhilesh #include <rte_cycles.h>
100124e18fSPavan Nikhilesh #include <rte_debug.h>
110124e18fSPavan Nikhilesh #include <rte_ethdev.h>
120124e18fSPavan Nikhilesh #include <rte_ether.h>
130124e18fSPavan Nikhilesh #include <rte_graph.h>
140124e18fSPavan Nikhilesh #include <rte_graph_worker.h>
150124e18fSPavan Nikhilesh #include <rte_ip.h>
160124e18fSPavan Nikhilesh #include <rte_ip_frag.h>
170124e18fSPavan Nikhilesh #include <rte_mbuf.h>
180124e18fSPavan Nikhilesh #include <rte_tcp.h>
190124e18fSPavan Nikhilesh #include <rte_udp.h>
200124e18fSPavan Nikhilesh 
210124e18fSPavan Nikhilesh #include "rte_node_ip4_api.h"
220124e18fSPavan Nikhilesh 
230124e18fSPavan Nikhilesh #include "ip4_reassembly_priv.h"
240124e18fSPavan Nikhilesh #include "node_private.h"
250124e18fSPavan Nikhilesh 
260124e18fSPavan Nikhilesh struct ip4_reassembly_elem {
270124e18fSPavan Nikhilesh 	struct ip4_reassembly_elem *next;
280124e18fSPavan Nikhilesh 	struct ip4_reassembly_ctx ctx;
290124e18fSPavan Nikhilesh 	rte_node_t node_id;
300124e18fSPavan Nikhilesh };
310124e18fSPavan Nikhilesh 
320124e18fSPavan Nikhilesh /* IP4 reassembly global data struct */
330124e18fSPavan Nikhilesh struct ip4_reassembly_node_main {
340124e18fSPavan Nikhilesh 	struct ip4_reassembly_elem *head;
350124e18fSPavan Nikhilesh };
360124e18fSPavan Nikhilesh 
370124e18fSPavan Nikhilesh typedef struct ip4_reassembly_ctx ip4_reassembly_ctx_t;
380124e18fSPavan Nikhilesh typedef struct ip4_reassembly_elem ip4_reassembly_elem_t;
390124e18fSPavan Nikhilesh 
400124e18fSPavan Nikhilesh static struct ip4_reassembly_node_main ip4_reassembly_main;
410124e18fSPavan Nikhilesh 
420124e18fSPavan Nikhilesh static uint16_t
430124e18fSPavan Nikhilesh ip4_reassembly_node_process(struct rte_graph *graph, struct rte_node *node, void **objs,
440124e18fSPavan Nikhilesh 			    uint16_t nb_objs)
450124e18fSPavan Nikhilesh {
460124e18fSPavan Nikhilesh #define PREFETCH_OFFSET 4
470124e18fSPavan Nikhilesh 	struct rte_mbuf *mbuf, *mbuf_out;
480124e18fSPavan Nikhilesh 	struct rte_ip_frag_death_row *dr;
490124e18fSPavan Nikhilesh 	struct ip4_reassembly_ctx *ctx;
500124e18fSPavan Nikhilesh 	struct rte_ipv4_hdr *ipv4_hdr;
510124e18fSPavan Nikhilesh 	struct rte_ip_frag_tbl *tbl;
520124e18fSPavan Nikhilesh 	void **to_next, **to_free;
530124e18fSPavan Nikhilesh 	uint16_t idx = 0;
540124e18fSPavan Nikhilesh 	int i;
550124e18fSPavan Nikhilesh 
560124e18fSPavan Nikhilesh 	ctx = (struct ip4_reassembly_ctx *)node->ctx;
570124e18fSPavan Nikhilesh 
580124e18fSPavan Nikhilesh 	/* Get core specific reassembly tbl */
590124e18fSPavan Nikhilesh 	tbl = ctx->tbl;
600124e18fSPavan Nikhilesh 	dr = ctx->dr;
610124e18fSPavan Nikhilesh 
620124e18fSPavan Nikhilesh 	for (i = 0; i < PREFETCH_OFFSET && i < nb_objs; i++) {
630124e18fSPavan Nikhilesh 		rte_prefetch0(rte_pktmbuf_mtod_offset((struct rte_mbuf *)objs[i], void *,
640124e18fSPavan Nikhilesh 						      sizeof(struct rte_ether_hdr)));
650124e18fSPavan Nikhilesh 	}
660124e18fSPavan Nikhilesh 
670124e18fSPavan Nikhilesh 	to_next = node->objs;
680124e18fSPavan Nikhilesh 	for (i = 0; i < nb_objs - PREFETCH_OFFSET; i++) {
690124e18fSPavan Nikhilesh #if RTE_GRAPH_BURST_SIZE > 64
700124e18fSPavan Nikhilesh 		/* Prefetch next-next mbufs */
710124e18fSPavan Nikhilesh 		if (likely(i + 8 < nb_objs))
720124e18fSPavan Nikhilesh 			rte_prefetch0(objs[i + 8]);
730124e18fSPavan Nikhilesh #endif
740124e18fSPavan Nikhilesh 		rte_prefetch0(rte_pktmbuf_mtod_offset((struct rte_mbuf *)objs[i + PREFETCH_OFFSET],
750124e18fSPavan Nikhilesh 						      void *, sizeof(struct rte_ether_hdr)));
760124e18fSPavan Nikhilesh 		mbuf = (struct rte_mbuf *)objs[i];
770124e18fSPavan Nikhilesh 
780124e18fSPavan Nikhilesh 		ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr *,
790124e18fSPavan Nikhilesh 						   sizeof(struct rte_ether_hdr));
800124e18fSPavan Nikhilesh 		if (rte_ipv4_frag_pkt_is_fragmented(ipv4_hdr)) {
810124e18fSPavan Nikhilesh 			/* prepare mbuf: setup l2_len/l3_len. */
820124e18fSPavan Nikhilesh 			mbuf->l2_len = sizeof(struct rte_ether_hdr);
830124e18fSPavan Nikhilesh 			mbuf->l3_len = sizeof(struct rte_ipv4_hdr);
840124e18fSPavan Nikhilesh 
850124e18fSPavan Nikhilesh 			mbuf_out = rte_ipv4_frag_reassemble_packet(tbl, dr, mbuf, rte_rdtsc(),
860124e18fSPavan Nikhilesh 								   ipv4_hdr);
870124e18fSPavan Nikhilesh 		} else {
880124e18fSPavan Nikhilesh 			mbuf_out = mbuf;
890124e18fSPavan Nikhilesh 		}
900124e18fSPavan Nikhilesh 
910124e18fSPavan Nikhilesh 		if (mbuf_out)
920124e18fSPavan Nikhilesh 			to_next[idx++] = (void *)mbuf_out;
930124e18fSPavan Nikhilesh 	}
940124e18fSPavan Nikhilesh 
950124e18fSPavan Nikhilesh 	for (; i < nb_objs; i++) {
960124e18fSPavan Nikhilesh 		mbuf = (struct rte_mbuf *)objs[i];
970124e18fSPavan Nikhilesh 
980124e18fSPavan Nikhilesh 		ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr *,
990124e18fSPavan Nikhilesh 						   sizeof(struct rte_ether_hdr));
1000124e18fSPavan Nikhilesh 		if (rte_ipv4_frag_pkt_is_fragmented(ipv4_hdr)) {
1010124e18fSPavan Nikhilesh 			/* prepare mbuf: setup l2_len/l3_len. */
1020124e18fSPavan Nikhilesh 			mbuf->l2_len = sizeof(struct rte_ether_hdr);
1030124e18fSPavan Nikhilesh 			mbuf->l3_len = sizeof(struct rte_ipv4_hdr);
1040124e18fSPavan Nikhilesh 
1050124e18fSPavan Nikhilesh 			mbuf_out = rte_ipv4_frag_reassemble_packet(tbl, dr, mbuf, rte_rdtsc(),
1060124e18fSPavan Nikhilesh 								   ipv4_hdr);
1070124e18fSPavan Nikhilesh 		} else {
1080124e18fSPavan Nikhilesh 			mbuf_out = mbuf;
1090124e18fSPavan Nikhilesh 		}
1100124e18fSPavan Nikhilesh 
1110124e18fSPavan Nikhilesh 		if (mbuf_out)
1120124e18fSPavan Nikhilesh 			to_next[idx++] = (void *)mbuf_out;
1130124e18fSPavan Nikhilesh 	}
1140124e18fSPavan Nikhilesh 	node->idx = idx;
1150124e18fSPavan Nikhilesh 	rte_node_next_stream_move(graph, node, 1);
1160124e18fSPavan Nikhilesh 	if (dr->cnt) {
1170124e18fSPavan Nikhilesh 		to_free = rte_node_next_stream_get(graph, node,
1180124e18fSPavan Nikhilesh 						   RTE_NODE_IP4_REASSEMBLY_NEXT_PKT_DROP, dr->cnt);
1190124e18fSPavan Nikhilesh 		rte_memcpy(to_free, dr->row, dr->cnt * sizeof(to_free[0]));
1200124e18fSPavan Nikhilesh 		rte_node_next_stream_put(graph, node, RTE_NODE_IP4_REASSEMBLY_NEXT_PKT_DROP,
1210124e18fSPavan Nikhilesh 					 dr->cnt);
1220124e18fSPavan Nikhilesh 		idx += dr->cnt;
123*be4c0cb4SPavan Nikhilesh 		NODE_INCREMENT_XSTAT_ID(node, 0, dr->cnt, dr->cnt);
1240124e18fSPavan Nikhilesh 		dr->cnt = 0;
1250124e18fSPavan Nikhilesh 	}
1260124e18fSPavan Nikhilesh 
1270124e18fSPavan Nikhilesh 	return idx;
1280124e18fSPavan Nikhilesh }
1290124e18fSPavan Nikhilesh 
1300124e18fSPavan Nikhilesh int
1310124e18fSPavan Nikhilesh rte_node_ip4_reassembly_configure(struct rte_node_ip4_reassembly_cfg *cfg, uint16_t cnt)
1320124e18fSPavan Nikhilesh {
1330124e18fSPavan Nikhilesh 	ip4_reassembly_elem_t *elem;
1340124e18fSPavan Nikhilesh 	int i;
1350124e18fSPavan Nikhilesh 
1360124e18fSPavan Nikhilesh 	for (i = 0; i < cnt; i++) {
1370124e18fSPavan Nikhilesh 		elem = malloc(sizeof(ip4_reassembly_elem_t));
1380124e18fSPavan Nikhilesh 		if (elem == NULL)
1390124e18fSPavan Nikhilesh 			return -ENOMEM;
1400124e18fSPavan Nikhilesh 		elem->ctx.dr = cfg[i].dr;
1410124e18fSPavan Nikhilesh 		elem->ctx.tbl = cfg[i].tbl;
1420124e18fSPavan Nikhilesh 		elem->node_id = cfg[i].node_id;
1430124e18fSPavan Nikhilesh 		elem->next = ip4_reassembly_main.head;
1440124e18fSPavan Nikhilesh 		ip4_reassembly_main.head = elem;
1450124e18fSPavan Nikhilesh 	}
1460124e18fSPavan Nikhilesh 
1470124e18fSPavan Nikhilesh 	return 0;
1480124e18fSPavan Nikhilesh }
1490124e18fSPavan Nikhilesh 
1500124e18fSPavan Nikhilesh static int
1510124e18fSPavan Nikhilesh ip4_reassembly_node_init(const struct rte_graph *graph, struct rte_node *node)
1520124e18fSPavan Nikhilesh {
1530124e18fSPavan Nikhilesh 	ip4_reassembly_ctx_t *ctx = (ip4_reassembly_ctx_t *)node->ctx;
1540124e18fSPavan Nikhilesh 	ip4_reassembly_elem_t *elem = ip4_reassembly_main.head;
1550124e18fSPavan Nikhilesh 
1560124e18fSPavan Nikhilesh 	RTE_SET_USED(graph);
1570124e18fSPavan Nikhilesh 	while (elem) {
1580124e18fSPavan Nikhilesh 		if (elem->node_id == node->id) {
1590124e18fSPavan Nikhilesh 			/* Update node specific context */
1600124e18fSPavan Nikhilesh 			memcpy(ctx, &elem->ctx, sizeof(ip4_reassembly_ctx_t));
1610124e18fSPavan Nikhilesh 			break;
1620124e18fSPavan Nikhilesh 		}
1630124e18fSPavan Nikhilesh 		elem = elem->next;
1640124e18fSPavan Nikhilesh 	}
1650124e18fSPavan Nikhilesh 
1660124e18fSPavan Nikhilesh 	return 0;
1670124e18fSPavan Nikhilesh }
1680124e18fSPavan Nikhilesh 
169*be4c0cb4SPavan Nikhilesh static struct rte_node_xstats ip4_reassembly_xstats = {
170*be4c0cb4SPavan Nikhilesh 	.nb_xstats = 1,
171*be4c0cb4SPavan Nikhilesh 	.xstat_desc = {
172*be4c0cb4SPavan Nikhilesh 		[0] = "ip4_reassembly_error",
173*be4c0cb4SPavan Nikhilesh 	},
174*be4c0cb4SPavan Nikhilesh };
175*be4c0cb4SPavan Nikhilesh 
1760124e18fSPavan Nikhilesh static struct rte_node_register ip4_reassembly_node = {
1770124e18fSPavan Nikhilesh 	.process = ip4_reassembly_node_process,
1780124e18fSPavan Nikhilesh 	.name = "ip4_reassembly",
1790124e18fSPavan Nikhilesh 
1800124e18fSPavan Nikhilesh 	.init = ip4_reassembly_node_init,
181*be4c0cb4SPavan Nikhilesh 	.xstats = &ip4_reassembly_xstats,
1820124e18fSPavan Nikhilesh 
1830124e18fSPavan Nikhilesh 	.nb_edges = RTE_NODE_IP4_REASSEMBLY_NEXT_PKT_DROP + 1,
1840124e18fSPavan Nikhilesh 	.next_nodes = {
1850124e18fSPavan Nikhilesh 		[RTE_NODE_IP4_REASSEMBLY_NEXT_PKT_DROP] = "pkt_drop",
1860124e18fSPavan Nikhilesh 	},
1870124e18fSPavan Nikhilesh };
1880124e18fSPavan Nikhilesh 
1890124e18fSPavan Nikhilesh struct rte_node_register *
1900124e18fSPavan Nikhilesh ip4_reassembly_node_get(void)
1910124e18fSPavan Nikhilesh {
1920124e18fSPavan Nikhilesh 	return &ip4_reassembly_node;
1930124e18fSPavan Nikhilesh }
1940124e18fSPavan Nikhilesh 
1950124e18fSPavan Nikhilesh RTE_NODE_REGISTER(ip4_reassembly_node);
196