Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2017 Intel Corporation
3 : : */
4 : :
5 : : #include <eal_export.h>
6 : : #include <rte_malloc.h>
7 : : #include <rte_cycles.h>
8 : : #include <rte_ethdev.h>
9 : :
10 : : #include "rte_gro.h"
11 : : #include "gro_tcp4.h"
12 : : #include "gro_tcp6.h"
13 : : #include "gro_udp4.h"
14 : : #include "gro_vxlan_tcp4.h"
15 : : #include "gro_vxlan_udp4.h"
16 : :
17 : : typedef void *(*gro_tbl_create_fn)(uint16_t socket_id,
18 : : uint16_t max_flow_num,
19 : : uint16_t max_item_per_flow);
20 : : typedef void (*gro_tbl_destroy_fn)(void *tbl);
21 : : typedef uint32_t (*gro_tbl_pkt_count_fn)(void *tbl);
22 : :
23 : : static gro_tbl_create_fn tbl_create_fn[RTE_GRO_TYPE_MAX_NUM] = {
24 : : gro_tcp4_tbl_create, gro_vxlan_tcp4_tbl_create,
25 : : gro_udp4_tbl_create, gro_vxlan_udp4_tbl_create, gro_tcp6_tbl_create, NULL};
26 : : static gro_tbl_destroy_fn tbl_destroy_fn[RTE_GRO_TYPE_MAX_NUM] = {
27 : : gro_tcp4_tbl_destroy, gro_vxlan_tcp4_tbl_destroy,
28 : : gro_udp4_tbl_destroy, gro_vxlan_udp4_tbl_destroy,
29 : : gro_tcp6_tbl_destroy,
30 : : NULL};
31 : : static gro_tbl_pkt_count_fn tbl_pkt_count_fn[RTE_GRO_TYPE_MAX_NUM] = {
32 : : gro_tcp4_tbl_pkt_count, gro_vxlan_tcp4_tbl_pkt_count,
33 : : gro_udp4_tbl_pkt_count, gro_vxlan_udp4_tbl_pkt_count,
34 : : gro_tcp6_tbl_pkt_count,
35 : : NULL};
36 : :
37 : : #define IS_IPV4_TCP_PKT(ptype) (RTE_ETH_IS_IPV4_HDR(ptype) && \
38 : : ((ptype & RTE_PTYPE_L4_TCP) == RTE_PTYPE_L4_TCP) && \
39 : : ((ptype & RTE_PTYPE_L4_FRAG) != RTE_PTYPE_L4_FRAG) && \
40 : : (RTE_ETH_IS_TUNNEL_PKT(ptype) == 0))
41 : :
42 : : /* GRO with extension headers is not supported */
43 : : #define IS_IPV6_TCP_PKT(ptype) (RTE_ETH_IS_IPV6_HDR(ptype) && \
44 : : ((ptype & RTE_PTYPE_L4_TCP) == RTE_PTYPE_L4_TCP) && \
45 : : ((ptype & RTE_PTYPE_L4_FRAG) != RTE_PTYPE_L4_FRAG) && \
46 : : (RTE_ETH_IS_TUNNEL_PKT(ptype) == 0))
47 : :
48 : : #define IS_IPV4_UDP_PKT(ptype) (RTE_ETH_IS_IPV4_HDR(ptype) && \
49 : : ((ptype & RTE_PTYPE_L4_UDP) == RTE_PTYPE_L4_UDP) && \
50 : : (RTE_ETH_IS_TUNNEL_PKT(ptype) == 0))
51 : :
52 : : #define IS_IPV4_VXLAN_TCP4_PKT(ptype) (RTE_ETH_IS_IPV4_HDR(ptype) && \
53 : : ((ptype & RTE_PTYPE_L4_UDP) == RTE_PTYPE_L4_UDP) && \
54 : : ((ptype & RTE_PTYPE_L4_FRAG) != RTE_PTYPE_L4_FRAG) && \
55 : : ((ptype & RTE_PTYPE_TUNNEL_VXLAN) == \
56 : : RTE_PTYPE_TUNNEL_VXLAN) && \
57 : : ((ptype & RTE_PTYPE_INNER_L4_TCP) == \
58 : : RTE_PTYPE_INNER_L4_TCP) && \
59 : : (((ptype & RTE_PTYPE_INNER_L3_MASK) == \
60 : : RTE_PTYPE_INNER_L3_IPV4) || \
61 : : ((ptype & RTE_PTYPE_INNER_L3_MASK) == \
62 : : RTE_PTYPE_INNER_L3_IPV4_EXT) || \
63 : : ((ptype & RTE_PTYPE_INNER_L3_MASK) == \
64 : : RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN)))
65 : :
66 : : #define IS_IPV4_VXLAN_UDP4_PKT(ptype) (RTE_ETH_IS_IPV4_HDR(ptype) && \
67 : : ((ptype & RTE_PTYPE_L4_UDP) == RTE_PTYPE_L4_UDP) && \
68 : : ((ptype & RTE_PTYPE_TUNNEL_VXLAN) == \
69 : : RTE_PTYPE_TUNNEL_VXLAN) && \
70 : : ((ptype & RTE_PTYPE_INNER_L4_UDP) == \
71 : : RTE_PTYPE_INNER_L4_UDP) && \
72 : : (((ptype & RTE_PTYPE_INNER_L3_MASK) == \
73 : : RTE_PTYPE_INNER_L3_IPV4) || \
74 : : ((ptype & RTE_PTYPE_INNER_L3_MASK) == \
75 : : RTE_PTYPE_INNER_L3_IPV4_EXT) || \
76 : : ((ptype & RTE_PTYPE_INNER_L3_MASK) == \
77 : : RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN)))
78 : :
79 : : /*
80 : : * GRO context structure. It keeps the table structures, which are
81 : : * used to merge packets, for different GRO types. Before using
82 : : * rte_gro_reassemble(), applications need to create the GRO context
83 : : * first.
84 : : */
85 : : struct gro_ctx {
86 : : /* GRO types to perform */
87 : : uint64_t gro_types;
88 : : /* reassembly tables */
89 : : void *tbls[RTE_GRO_TYPE_MAX_NUM];
90 : : };
91 : :
92 : : RTE_EXPORT_SYMBOL(rte_gro_ctx_create)
93 : : void *
94 : 0 : rte_gro_ctx_create(const struct rte_gro_param *param)
95 : : {
96 : : struct gro_ctx *gro_ctx;
97 : : gro_tbl_create_fn create_tbl_fn;
98 : : uint64_t gro_type_flag = 0;
99 : : uint64_t gro_types = 0;
100 : : uint8_t i;
101 : :
102 : 0 : gro_ctx = rte_zmalloc_socket(__func__,
103 : : sizeof(struct gro_ctx),
104 : : RTE_CACHE_LINE_SIZE,
105 : 0 : param->socket_id);
106 [ # # ]: 0 : if (gro_ctx == NULL)
107 : : return NULL;
108 : :
109 [ # # ]: 0 : for (i = 0; i < RTE_GRO_TYPE_MAX_NUM; i++) {
110 : 0 : gro_type_flag = 1ULL << i;
111 [ # # ]: 0 : if ((param->gro_types & gro_type_flag) == 0)
112 : 0 : continue;
113 : :
114 : 0 : create_tbl_fn = tbl_create_fn[i];
115 [ # # ]: 0 : if (create_tbl_fn == NULL)
116 : 0 : continue;
117 : :
118 : 0 : gro_ctx->tbls[i] = create_tbl_fn(param->socket_id,
119 : 0 : param->max_flow_num,
120 : 0 : param->max_item_per_flow);
121 [ # # ]: 0 : if (gro_ctx->tbls[i] == NULL) {
122 : : /* destroy all created tables */
123 : 0 : gro_ctx->gro_types = gro_types;
124 : 0 : rte_gro_ctx_destroy(gro_ctx);
125 : 0 : return NULL;
126 : : }
127 : 0 : gro_types |= gro_type_flag;
128 : : }
129 : 0 : gro_ctx->gro_types = param->gro_types;
130 : :
131 : 0 : return gro_ctx;
132 : : }
133 : :
134 : : RTE_EXPORT_SYMBOL(rte_gro_ctx_destroy)
135 : : void
136 : 0 : rte_gro_ctx_destroy(void *ctx)
137 : : {
138 : : gro_tbl_destroy_fn destroy_tbl_fn;
139 : : struct gro_ctx *gro_ctx = ctx;
140 : : uint64_t gro_type_flag;
141 : : uint8_t i;
142 : :
143 [ # # ]: 0 : for (i = 0; i < RTE_GRO_TYPE_MAX_NUM; i++) {
144 : 0 : gro_type_flag = 1ULL << i;
145 [ # # ]: 0 : if ((gro_ctx->gro_types & gro_type_flag) == 0)
146 : 0 : continue;
147 : 0 : destroy_tbl_fn = tbl_destroy_fn[i];
148 [ # # ]: 0 : if (destroy_tbl_fn)
149 : 0 : destroy_tbl_fn(gro_ctx->tbls[i]);
150 : : }
151 : 0 : rte_free(gro_ctx);
152 : 0 : }
153 : :
154 : : RTE_EXPORT_SYMBOL(rte_gro_reassemble_burst)
155 : : uint16_t
156 : 0 : rte_gro_reassemble_burst(struct rte_mbuf **pkts,
157 : : uint16_t nb_pkts,
158 : : const struct rte_gro_param *param)
159 : : {
160 : : /* allocate a reassembly table for TCP/IPv4 GRO */
161 : : struct gro_tcp4_tbl tcp_tbl;
162 : : struct gro_tcp4_flow tcp_flows[RTE_GRO_MAX_BURST_ITEM_NUM];
163 : 0 : struct gro_tcp_item tcp_items[RTE_GRO_MAX_BURST_ITEM_NUM] = {{0} };
164 : :
165 : : struct gro_tcp6_tbl tcp6_tbl;
166 : : struct gro_tcp6_flow tcp6_flows[RTE_GRO_MAX_BURST_ITEM_NUM];
167 : 0 : struct gro_tcp_item tcp6_items[RTE_GRO_MAX_BURST_ITEM_NUM] = {{0} };
168 : :
169 : : /* allocate a reassembly table for UDP/IPv4 GRO */
170 : : struct gro_udp4_tbl udp_tbl;
171 : : struct gro_udp4_flow udp_flows[RTE_GRO_MAX_BURST_ITEM_NUM];
172 : 0 : struct gro_udp4_item udp_items[RTE_GRO_MAX_BURST_ITEM_NUM] = {{0} };
173 : :
174 : : /* Allocate a reassembly table for VXLAN TCP GRO */
175 : : struct gro_vxlan_tcp4_tbl vxlan_tcp_tbl;
176 : : struct gro_vxlan_tcp4_flow vxlan_tcp_flows[RTE_GRO_MAX_BURST_ITEM_NUM];
177 : 0 : struct gro_vxlan_tcp4_item vxlan_tcp_items[RTE_GRO_MAX_BURST_ITEM_NUM]
178 : : = {{{0}, 0, 0} };
179 : :
180 : : /* Allocate a reassembly table for VXLAN UDP GRO */
181 : : struct gro_vxlan_udp4_tbl vxlan_udp_tbl;
182 : : struct gro_vxlan_udp4_flow vxlan_udp_flows[RTE_GRO_MAX_BURST_ITEM_NUM];
183 : 0 : struct gro_vxlan_udp4_item vxlan_udp_items[RTE_GRO_MAX_BURST_ITEM_NUM]
184 : : = {{{0}} };
185 : :
186 : : uint32_t item_num;
187 : : int32_t ret;
188 : : uint16_t i, unprocess_num = 0, nb_after_gro = nb_pkts;
189 : : uint8_t do_tcp4_gro = 0, do_vxlan_tcp_gro = 0, do_udp4_gro = 0,
190 : : do_vxlan_udp_gro = 0, do_tcp6_gro = 0;
191 : :
192 [ # # ]: 0 : if (unlikely((param->gro_types & (RTE_GRO_IPV4_VXLAN_TCP_IPV4 |
193 : : RTE_GRO_TCP_IPV4 | RTE_GRO_TCP_IPV6 |
194 : : RTE_GRO_IPV4_VXLAN_UDP_IPV4 |
195 : : RTE_GRO_UDP_IPV4)) == 0))
196 : : return nb_pkts;
197 : :
198 : : /* Get the maximum number of packets */
199 : 0 : item_num = RTE_MIN(nb_pkts, (param->max_flow_num *
200 : : param->max_item_per_flow));
201 : 0 : item_num = RTE_MIN(item_num, RTE_GRO_MAX_BURST_ITEM_NUM);
202 : :
203 [ # # ]: 0 : if (param->gro_types & RTE_GRO_IPV4_VXLAN_TCP_IPV4) {
204 [ # # ]: 0 : for (i = 0; i < item_num; i++)
205 : 0 : vxlan_tcp_flows[i].start_index = INVALID_ARRAY_INDEX;
206 : :
207 : 0 : vxlan_tcp_tbl.flows = vxlan_tcp_flows;
208 : 0 : vxlan_tcp_tbl.items = vxlan_tcp_items;
209 : 0 : vxlan_tcp_tbl.flow_num = 0;
210 : 0 : vxlan_tcp_tbl.item_num = 0;
211 : 0 : vxlan_tcp_tbl.max_flow_num = item_num;
212 : 0 : vxlan_tcp_tbl.max_item_num = item_num;
213 : : do_vxlan_tcp_gro = 1;
214 : : }
215 : :
216 [ # # ]: 0 : if (param->gro_types & RTE_GRO_IPV4_VXLAN_UDP_IPV4) {
217 [ # # ]: 0 : for (i = 0; i < item_num; i++)
218 : 0 : vxlan_udp_flows[i].start_index = INVALID_ARRAY_INDEX;
219 : :
220 : 0 : vxlan_udp_tbl.flows = vxlan_udp_flows;
221 : 0 : vxlan_udp_tbl.items = vxlan_udp_items;
222 : 0 : vxlan_udp_tbl.flow_num = 0;
223 : 0 : vxlan_udp_tbl.item_num = 0;
224 : 0 : vxlan_udp_tbl.max_flow_num = item_num;
225 : 0 : vxlan_udp_tbl.max_item_num = item_num;
226 : : do_vxlan_udp_gro = 1;
227 : : }
228 : :
229 [ # # ]: 0 : if (param->gro_types & RTE_GRO_TCP_IPV4) {
230 [ # # ]: 0 : for (i = 0; i < item_num; i++)
231 : 0 : tcp_flows[i].start_index = INVALID_ARRAY_INDEX;
232 : :
233 : 0 : tcp_tbl.flows = tcp_flows;
234 : 0 : tcp_tbl.items = tcp_items;
235 : 0 : tcp_tbl.flow_num = 0;
236 : 0 : tcp_tbl.item_num = 0;
237 : 0 : tcp_tbl.max_flow_num = item_num;
238 : 0 : tcp_tbl.max_item_num = item_num;
239 : : do_tcp4_gro = 1;
240 : : }
241 : :
242 [ # # ]: 0 : if (param->gro_types & RTE_GRO_UDP_IPV4) {
243 [ # # ]: 0 : for (i = 0; i < item_num; i++)
244 : 0 : udp_flows[i].start_index = INVALID_ARRAY_INDEX;
245 : :
246 : 0 : udp_tbl.flows = udp_flows;
247 : 0 : udp_tbl.items = udp_items;
248 : 0 : udp_tbl.flow_num = 0;
249 : 0 : udp_tbl.item_num = 0;
250 : 0 : udp_tbl.max_flow_num = item_num;
251 : 0 : udp_tbl.max_item_num = item_num;
252 : : do_udp4_gro = 1;
253 : : }
254 : :
255 [ # # ]: 0 : if (param->gro_types & RTE_GRO_TCP_IPV6) {
256 [ # # ]: 0 : for (i = 0; i < item_num; i++)
257 : 0 : tcp6_flows[i].start_index = INVALID_ARRAY_INDEX;
258 : :
259 : 0 : tcp6_tbl.flows = tcp6_flows;
260 : 0 : tcp6_tbl.items = tcp6_items;
261 : 0 : tcp6_tbl.flow_num = 0;
262 : 0 : tcp6_tbl.item_num = 0;
263 : 0 : tcp6_tbl.max_flow_num = item_num;
264 : 0 : tcp6_tbl.max_item_num = item_num;
265 : : do_tcp6_gro = 1;
266 : : }
267 : :
268 [ # # ]: 0 : for (i = 0; i < nb_pkts; i++) {
269 : : /*
270 : : * The timestamp is ignored, since all packets
271 : : * will be flushed from the tables.
272 : : */
273 [ # # # # : 0 : if (IS_IPV4_VXLAN_TCP4_PKT(pkts[i]->packet_type) &&
# # # # #
# # # ]
274 : : do_vxlan_tcp_gro) {
275 : 0 : ret = gro_vxlan_tcp4_reassemble(pkts[i],
276 : : &vxlan_tcp_tbl, 0);
277 [ # # ]: 0 : if (ret > 0)
278 : : /* Merge successfully */
279 : 0 : nb_after_gro--;
280 [ # # ]: 0 : else if (ret < 0)
281 : 0 : pkts[unprocess_num++] = pkts[i];
282 [ # # # # : 0 : } else if (IS_IPV4_VXLAN_UDP4_PKT(pkts[i]->packet_type) &&
# # # # ]
283 : : do_vxlan_udp_gro) {
284 : 0 : ret = gro_vxlan_udp4_reassemble(pkts[i],
285 : : &vxlan_udp_tbl, 0);
286 [ # # ]: 0 : if (ret > 0)
287 : : /* Merge successfully */
288 : 0 : nb_after_gro--;
289 [ # # ]: 0 : else if (ret < 0)
290 : 0 : pkts[unprocess_num++] = pkts[i];
291 [ # # # # : 0 : } else if (IS_IPV4_TCP_PKT(pkts[i]->packet_type) &&
# # # # ]
292 : : do_tcp4_gro) {
293 : 0 : ret = gro_tcp4_reassemble(pkts[i], &tcp_tbl, 0);
294 [ # # ]: 0 : if (ret > 0)
295 : : /* merge successfully */
296 : 0 : nb_after_gro--;
297 [ # # ]: 0 : else if (ret < 0)
298 : 0 : pkts[unprocess_num++] = pkts[i];
299 [ # # # # ]: 0 : } else if (IS_IPV4_UDP_PKT(pkts[i]->packet_type) &&
300 : : do_udp4_gro) {
301 : 0 : ret = gro_udp4_reassemble(pkts[i], &udp_tbl, 0);
302 [ # # ]: 0 : if (ret > 0)
303 : : /* merge successfully */
304 : 0 : nb_after_gro--;
305 [ # # ]: 0 : else if (ret < 0)
306 : 0 : pkts[unprocess_num++] = pkts[i];
307 [ # # # # : 0 : } else if (IS_IPV6_TCP_PKT(pkts[i]->packet_type) &&
# # # # ]
308 : : do_tcp6_gro) {
309 : 0 : ret = gro_tcp6_reassemble(pkts[i], &tcp6_tbl, 0);
310 [ # # ]: 0 : if (ret > 0)
311 : : /* merge successfully */
312 : 0 : nb_after_gro--;
313 [ # # ]: 0 : else if (ret < 0)
314 : 0 : pkts[unprocess_num++] = pkts[i];
315 : : } else
316 : 0 : pkts[unprocess_num++] = pkts[i];
317 : : }
318 : :
319 [ # # ]: 0 : if ((nb_after_gro < nb_pkts)
320 : : || (unprocess_num < nb_pkts)) {
321 : :
322 : : i = unprocess_num;
323 : :
324 : : /* Flush all packets from the tables */
325 [ # # ]: 0 : if (do_vxlan_tcp_gro) {
326 : 0 : i += gro_vxlan_tcp4_tbl_timeout_flush(&vxlan_tcp_tbl,
327 : 0 : 0, &pkts[i], nb_pkts - i);
328 : : }
329 : :
330 [ # # ]: 0 : if (do_vxlan_udp_gro) {
331 : 0 : i += gro_vxlan_udp4_tbl_timeout_flush(&vxlan_udp_tbl,
332 : 0 : 0, &pkts[i], nb_pkts - i);
333 : :
334 : : }
335 : :
336 [ # # ]: 0 : if (do_tcp4_gro) {
337 : 0 : i += gro_tcp4_tbl_timeout_flush(&tcp_tbl, 0,
338 : 0 : &pkts[i], nb_pkts - i);
339 : : }
340 : :
341 [ # # ]: 0 : if (do_udp4_gro) {
342 : 0 : i += gro_udp4_tbl_timeout_flush(&udp_tbl, 0,
343 : 0 : &pkts[i], nb_pkts - i);
344 : : }
345 : :
346 [ # # ]: 0 : if (do_tcp6_gro) {
347 : 0 : i += gro_tcp6_tbl_timeout_flush(&tcp6_tbl, 0,
348 : 0 : &pkts[i], nb_pkts - i);
349 : : }
350 : : }
351 : :
352 : : return nb_after_gro;
353 : : }
354 : :
355 : : RTE_EXPORT_SYMBOL(rte_gro_reassemble)
356 : : uint16_t
357 : 0 : rte_gro_reassemble(struct rte_mbuf **pkts,
358 : : uint16_t nb_pkts,
359 : : void *ctx)
360 : : {
361 : : struct gro_ctx *gro_ctx = ctx;
362 : : void *tcp_tbl, *udp_tbl, *vxlan_tcp_tbl, *vxlan_udp_tbl, *tcp6_tbl;
363 : : uint64_t current_time;
364 : : uint16_t i, unprocess_num = 0;
365 : : uint8_t do_tcp4_gro, do_vxlan_tcp_gro, do_udp4_gro, do_vxlan_udp_gro, do_tcp6_gro;
366 : :
367 [ # # ]: 0 : if (unlikely((gro_ctx->gro_types & (RTE_GRO_IPV4_VXLAN_TCP_IPV4 |
368 : : RTE_GRO_TCP_IPV4 | RTE_GRO_TCP_IPV6 |
369 : : RTE_GRO_IPV4_VXLAN_UDP_IPV4 |
370 : : RTE_GRO_UDP_IPV4)) == 0))
371 : : return nb_pkts;
372 : :
373 : 0 : tcp_tbl = gro_ctx->tbls[RTE_GRO_TCP_IPV4_INDEX];
374 : 0 : vxlan_tcp_tbl = gro_ctx->tbls[RTE_GRO_IPV4_VXLAN_TCP_IPV4_INDEX];
375 : 0 : udp_tbl = gro_ctx->tbls[RTE_GRO_UDP_IPV4_INDEX];
376 : 0 : vxlan_udp_tbl = gro_ctx->tbls[RTE_GRO_IPV4_VXLAN_UDP_IPV4_INDEX];
377 : 0 : tcp6_tbl = gro_ctx->tbls[RTE_GRO_TCP_IPV6_INDEX];
378 : :
379 : 0 : do_tcp4_gro = (gro_ctx->gro_types & RTE_GRO_TCP_IPV4) ==
380 : : RTE_GRO_TCP_IPV4;
381 : 0 : do_vxlan_tcp_gro = (gro_ctx->gro_types & RTE_GRO_IPV4_VXLAN_TCP_IPV4) ==
382 : : RTE_GRO_IPV4_VXLAN_TCP_IPV4;
383 : 0 : do_udp4_gro = (gro_ctx->gro_types & RTE_GRO_UDP_IPV4) ==
384 : : RTE_GRO_UDP_IPV4;
385 : 0 : do_vxlan_udp_gro = (gro_ctx->gro_types & RTE_GRO_IPV4_VXLAN_UDP_IPV4) ==
386 : : RTE_GRO_IPV4_VXLAN_UDP_IPV4;
387 : 0 : do_tcp6_gro = (gro_ctx->gro_types & RTE_GRO_TCP_IPV6) == RTE_GRO_TCP_IPV6;
388 : :
389 : : current_time = rte_rdtsc();
390 : :
391 [ # # ]: 0 : for (i = 0; i < nb_pkts; i++) {
392 [ # # # # : 0 : if (IS_IPV4_VXLAN_TCP4_PKT(pkts[i]->packet_type) &&
# # # # #
# # # ]
393 : : do_vxlan_tcp_gro) {
394 [ # # ]: 0 : if (gro_vxlan_tcp4_reassemble(pkts[i], vxlan_tcp_tbl,
395 : : current_time) < 0)
396 : 0 : pkts[unprocess_num++] = pkts[i];
397 [ # # # # : 0 : } else if (IS_IPV4_VXLAN_UDP4_PKT(pkts[i]->packet_type) &&
# # # # ]
398 : : do_vxlan_udp_gro) {
399 [ # # ]: 0 : if (gro_vxlan_udp4_reassemble(pkts[i], vxlan_udp_tbl,
400 : : current_time) < 0)
401 : 0 : pkts[unprocess_num++] = pkts[i];
402 [ # # # # : 0 : } else if (IS_IPV4_TCP_PKT(pkts[i]->packet_type) &&
# # # # ]
403 : : do_tcp4_gro) {
404 [ # # ]: 0 : if (gro_tcp4_reassemble(pkts[i], tcp_tbl,
405 : : current_time) < 0)
406 : 0 : pkts[unprocess_num++] = pkts[i];
407 [ # # # # ]: 0 : } else if (IS_IPV4_UDP_PKT(pkts[i]->packet_type) &&
408 : : do_udp4_gro) {
409 [ # # ]: 0 : if (gro_udp4_reassemble(pkts[i], udp_tbl,
410 : : current_time) < 0)
411 : 0 : pkts[unprocess_num++] = pkts[i];
412 [ # # # # : 0 : } else if (IS_IPV6_TCP_PKT(pkts[i]->packet_type) &&
# # # # ]
413 : : do_tcp6_gro) {
414 [ # # ]: 0 : if (gro_tcp6_reassemble(pkts[i], tcp6_tbl,
415 : : current_time) < 0)
416 : 0 : pkts[unprocess_num++] = pkts[i];
417 : : } else
418 : 0 : pkts[unprocess_num++] = pkts[i];
419 : : }
420 : :
421 : : return unprocess_num;
422 : : }
423 : :
424 : : RTE_EXPORT_SYMBOL(rte_gro_timeout_flush)
425 : : uint16_t
426 : 0 : rte_gro_timeout_flush(void *ctx,
427 : : uint64_t timeout_cycles,
428 : : uint64_t gro_types,
429 : : struct rte_mbuf **out,
430 : : uint16_t max_nb_out)
431 : : {
432 : : struct gro_ctx *gro_ctx = ctx;
433 : : uint64_t flush_timestamp;
434 : : uint16_t num = 0;
435 : : uint16_t left_nb_out = max_nb_out;
436 : :
437 : 0 : gro_types = gro_types & gro_ctx->gro_types;
438 : 0 : flush_timestamp = rte_rdtsc() - timeout_cycles;
439 : :
440 [ # # ]: 0 : if (gro_types & RTE_GRO_IPV4_VXLAN_TCP_IPV4) {
441 : 0 : num = gro_vxlan_tcp4_tbl_timeout_flush(gro_ctx->tbls[
442 : : RTE_GRO_IPV4_VXLAN_TCP_IPV4_INDEX],
443 : : flush_timestamp, out, left_nb_out);
444 : 0 : left_nb_out = max_nb_out - num;
445 : : }
446 : :
447 [ # # # # ]: 0 : if ((gro_types & RTE_GRO_IPV4_VXLAN_UDP_IPV4) && left_nb_out > 0) {
448 : 0 : num += gro_vxlan_udp4_tbl_timeout_flush(gro_ctx->tbls[
449 : : RTE_GRO_IPV4_VXLAN_UDP_IPV4_INDEX],
450 : 0 : flush_timestamp, &out[num], left_nb_out);
451 : 0 : left_nb_out = max_nb_out - num;
452 : : }
453 : :
454 : : /* If no available space in 'out', stop flushing. */
455 [ # # # # ]: 0 : if ((gro_types & RTE_GRO_TCP_IPV4) && left_nb_out > 0) {
456 : 0 : num += gro_tcp4_tbl_timeout_flush(
457 : 0 : gro_ctx->tbls[RTE_GRO_TCP_IPV4_INDEX],
458 : : flush_timestamp,
459 : 0 : &out[num], left_nb_out);
460 : 0 : left_nb_out = max_nb_out - num;
461 : : }
462 : :
463 : : /* If no available space in 'out', stop flushing. */
464 [ # # # # ]: 0 : if ((gro_types & RTE_GRO_UDP_IPV4) && left_nb_out > 0) {
465 : 0 : num += gro_udp4_tbl_timeout_flush(
466 : 0 : gro_ctx->tbls[RTE_GRO_UDP_IPV4_INDEX],
467 : : flush_timestamp,
468 : 0 : &out[num], left_nb_out);
469 : 0 : left_nb_out = max_nb_out - num;
470 : : }
471 : :
472 [ # # # # ]: 0 : if ((gro_types & RTE_GRO_TCP_IPV6) && left_nb_out > 0) {
473 : 0 : num += gro_tcp6_tbl_timeout_flush(
474 : 0 : gro_ctx->tbls[RTE_GRO_TCP_IPV6_INDEX],
475 : : flush_timestamp,
476 : 0 : &out[num], left_nb_out);
477 : :
478 : : }
479 : :
480 : 0 : return num;
481 : : }
482 : :
483 : : RTE_EXPORT_SYMBOL(rte_gro_get_pkt_count)
484 : : uint64_t
485 : 0 : rte_gro_get_pkt_count(void *ctx)
486 : : {
487 : : struct gro_ctx *gro_ctx = ctx;
488 : : gro_tbl_pkt_count_fn pkt_count_fn;
489 : 0 : uint64_t gro_types = gro_ctx->gro_types, flag;
490 : : uint64_t item_num = 0;
491 : : uint8_t i;
492 : :
493 [ # # ]: 0 : for (i = 0; i < RTE_GRO_TYPE_MAX_NUM && gro_types; i++) {
494 : 0 : flag = 1ULL << i;
495 [ # # ]: 0 : if ((gro_types & flag) == 0)
496 : 0 : continue;
497 : :
498 : 0 : gro_types ^= flag;
499 : 0 : pkt_count_fn = tbl_pkt_count_fn[i];
500 [ # # ]: 0 : if (pkt_count_fn)
501 : 0 : item_num += pkt_count_fn(gro_ctx->tbls[i]);
502 : : }
503 : :
504 : 0 : return item_num;
505 : : }
|