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