Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2023 Marvell.
3 : : */
4 : :
5 : : #include <arpa/inet.h>
6 : : #include <stdlib.h>
7 : : #include <sys/socket.h>
8 : :
9 : : #include <eal_export.h>
10 : : #include <rte_cycles.h>
11 : : #include <rte_debug.h>
12 : : #include <rte_ethdev.h>
13 : : #include <rte_ether.h>
14 : : #include <rte_graph.h>
15 : : #include <rte_graph_worker.h>
16 : : #include <rte_ip.h>
17 : : #include <rte_ip_frag.h>
18 : : #include <rte_mbuf.h>
19 : : #include <rte_tcp.h>
20 : : #include <rte_udp.h>
21 : :
22 : : #include "rte_node_ip4_api.h"
23 : :
24 : : #include "ip4_reassembly_priv.h"
25 : : #include "node_private.h"
26 : :
27 : : struct ip4_reassembly_elem {
28 : : struct ip4_reassembly_elem *next;
29 : : struct ip4_reassembly_ctx ctx;
30 : : rte_node_t node_id;
31 : : };
32 : :
33 : : /* IP4 reassembly global data struct */
34 : : struct ip4_reassembly_node_main {
35 : : struct ip4_reassembly_elem *head;
36 : : };
37 : :
38 : : typedef struct ip4_reassembly_ctx ip4_reassembly_ctx_t;
39 : : typedef struct ip4_reassembly_elem ip4_reassembly_elem_t;
40 : :
41 : : static struct ip4_reassembly_node_main ip4_reassembly_main;
42 : :
43 : : static uint16_t
44 : 0 : ip4_reassembly_node_process(struct rte_graph *graph, struct rte_node *node, void **objs,
45 : : uint16_t nb_objs)
46 : : {
47 : : #define PREFETCH_OFFSET 4
48 : : struct rte_mbuf *mbuf, *mbuf_out;
49 : : struct rte_ip_frag_death_row *dr;
50 : : struct ip4_reassembly_ctx *ctx;
51 : : struct rte_ipv4_hdr *ipv4_hdr;
52 : : struct rte_ip_frag_tbl *tbl;
53 : : void **to_next, **to_free;
54 : : uint16_t idx = 0;
55 : : int i;
56 : :
57 : : ctx = (struct ip4_reassembly_ctx *)node->ctx;
58 : :
59 : : /* Get core specific reassembly tbl */
60 : 0 : tbl = ctx->tbl;
61 : 0 : dr = ctx->dr;
62 : :
63 [ # # # # ]: 0 : for (i = 0; i < PREFETCH_OFFSET && i < nb_objs; i++) {
64 : 0 : rte_prefetch0(rte_pktmbuf_mtod_offset((struct rte_mbuf *)objs[i], void *,
65 : : sizeof(struct rte_ether_hdr)));
66 : : }
67 : :
68 : 0 : to_next = node->objs;
69 [ # # ]: 0 : for (i = 0; i < nb_objs - PREFETCH_OFFSET; i++) {
70 : : #if RTE_GRAPH_BURST_SIZE > 64
71 : : /* Prefetch next-next mbufs */
72 [ # # ]: 0 : if (likely(i + 8 < nb_objs))
73 : 0 : rte_prefetch0(objs[i + 8]);
74 : : #endif
75 : 0 : rte_prefetch0(rte_pktmbuf_mtod_offset((struct rte_mbuf *)objs[i + PREFETCH_OFFSET],
76 : : void *, sizeof(struct rte_ether_hdr)));
77 : 0 : mbuf = (struct rte_mbuf *)objs[i];
78 : :
79 [ # # ]: 0 : ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr *,
80 : : sizeof(struct rte_ether_hdr));
81 [ # # ]: 0 : if (rte_ipv4_frag_pkt_is_fragmented(ipv4_hdr)) {
82 : : /* prepare mbuf: setup l2_len/l3_len. */
83 : 0 : mbuf->l2_len = sizeof(struct rte_ether_hdr);
84 : 0 : mbuf->l3_len = sizeof(struct rte_ipv4_hdr);
85 : :
86 : 0 : mbuf_out = rte_ipv4_frag_reassemble_packet(tbl, dr, mbuf, rte_rdtsc(),
87 : : ipv4_hdr);
88 : : } else {
89 : : mbuf_out = mbuf;
90 : : }
91 : :
92 [ # # ]: 0 : if (mbuf_out)
93 : 0 : to_next[idx++] = (void *)mbuf_out;
94 : : }
95 : :
96 [ # # ]: 0 : for (; i < nb_objs; i++) {
97 : 0 : mbuf = (struct rte_mbuf *)objs[i];
98 : :
99 [ # # ]: 0 : ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr *,
100 : : sizeof(struct rte_ether_hdr));
101 [ # # ]: 0 : if (rte_ipv4_frag_pkt_is_fragmented(ipv4_hdr)) {
102 : : /* prepare mbuf: setup l2_len/l3_len. */
103 : 0 : mbuf->l2_len = sizeof(struct rte_ether_hdr);
104 : 0 : mbuf->l3_len = sizeof(struct rte_ipv4_hdr);
105 : :
106 : 0 : mbuf_out = rte_ipv4_frag_reassemble_packet(tbl, dr, mbuf, rte_rdtsc(),
107 : : ipv4_hdr);
108 : : } else {
109 : : mbuf_out = mbuf;
110 : : }
111 : :
112 [ # # ]: 0 : if (mbuf_out)
113 : 0 : to_next[idx++] = (void *)mbuf_out;
114 : : }
115 : 0 : node->idx = idx;
116 : 0 : rte_node_next_stream_move(graph, node, 1);
117 [ # # ]: 0 : if (dr->cnt) {
118 : 0 : to_free = rte_node_next_stream_get(graph, node,
119 : : RTE_NODE_IP4_REASSEMBLY_NEXT_PKT_DROP, dr->cnt);
120 [ # # ]: 0 : rte_memcpy(to_free, dr->row, dr->cnt * sizeof(to_free[0]));
121 : 0 : rte_node_next_stream_put(graph, node, RTE_NODE_IP4_REASSEMBLY_NEXT_PKT_DROP,
122 [ # # ]: 0 : dr->cnt);
123 : 0 : idx += dr->cnt;
124 [ # # ]: 0 : NODE_INCREMENT_XSTAT_ID(node, 0, dr->cnt, dr->cnt);
125 : 0 : dr->cnt = 0;
126 : : }
127 : :
128 : 0 : return idx;
129 : : }
130 : :
131 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_node_ip4_reassembly_configure, 23.11)
132 : : int
133 : 0 : rte_node_ip4_reassembly_configure(struct rte_node_ip4_reassembly_cfg *cfg, uint16_t cnt)
134 : : {
135 : : ip4_reassembly_elem_t *elem;
136 : : int i;
137 : :
138 [ # # ]: 0 : for (i = 0; i < cnt; i++) {
139 : 0 : elem = malloc(sizeof(ip4_reassembly_elem_t));
140 [ # # ]: 0 : if (elem == NULL)
141 : : return -ENOMEM;
142 : 0 : elem->ctx.dr = cfg[i].dr;
143 : 0 : elem->ctx.tbl = cfg[i].tbl;
144 : 0 : elem->node_id = cfg[i].node_id;
145 : 0 : elem->next = ip4_reassembly_main.head;
146 : 0 : ip4_reassembly_main.head = elem;
147 : : }
148 : :
149 : : return 0;
150 : : }
151 : :
152 : : static int
153 : 0 : ip4_reassembly_node_init(const struct rte_graph *graph, struct rte_node *node)
154 : : {
155 : 0 : ip4_reassembly_ctx_t *ctx = (ip4_reassembly_ctx_t *)node->ctx;
156 : 0 : ip4_reassembly_elem_t *elem = ip4_reassembly_main.head;
157 : :
158 : : RTE_SET_USED(graph);
159 [ # # ]: 0 : while (elem) {
160 [ # # ]: 0 : if (elem->node_id == node->id) {
161 : : /* Update node specific context */
162 : 0 : memcpy(ctx, &elem->ctx, sizeof(ip4_reassembly_ctx_t));
163 : : break;
164 : : }
165 : 0 : elem = elem->next;
166 : : }
167 : :
168 : 0 : return 0;
169 : : }
170 : :
171 : : static struct rte_node_xstats ip4_reassembly_xstats = {
172 : : .nb_xstats = 1,
173 : : .xstat_desc = {
174 : : [0] = "ip4_reassembly_error",
175 : : },
176 : : };
177 : :
178 : : static struct rte_node_register ip4_reassembly_node = {
179 : : .process = ip4_reassembly_node_process,
180 : : .name = "ip4_reassembly",
181 : :
182 : : .init = ip4_reassembly_node_init,
183 : : .xstats = &ip4_reassembly_xstats,
184 : :
185 : : .nb_edges = RTE_NODE_IP4_REASSEMBLY_NEXT_PKT_DROP + 1,
186 : : .next_nodes = {
187 : : [RTE_NODE_IP4_REASSEMBLY_NEXT_PKT_DROP] = "pkt_drop",
188 : : },
189 : : };
190 : :
191 : : struct rte_node_register *
192 : 0 : ip4_reassembly_node_get(void)
193 : : {
194 : 0 : return &ip4_reassembly_node;
195 : : }
196 : :
197 : 252 : RTE_NODE_REGISTER(ip4_reassembly_node);
|