[PATCH v2] gro : improve GRO performance based on hash table

Stephen Hemminger stephen at networkplumber.org
Sun Nov 16 17:52:37 CET 2025


On Sun, 16 Nov 2025 11:36:34 +0530
Kumara Parameshwaran <kumaraparamesh92 at gmail.com> wrote:

> Use cuckoo hash library in GRO for flow flookup
> 
> Signed-off-by: Kumara Parameshwaran <kumaraparamesh92 at gmail.com>


Need  test about what happens when table is DoS attacked.

> 
> Fix warnings and more validatation to the test
> 
>  app/test/meson.build |   1 +
>  app/test/test_gro.c  | 237 +++++++++++++++++++++++++++++++++++++++++++
>  lib/gro/gro_tcp4.c   |  60 ++++++-----
>  lib/gro/gro_tcp4.h   |   2 +
>  lib/gro/meson.build  |   2 +-
>  5 files changed, 278 insertions(+), 24 deletions(-)
>  create mode 100644 app/test/test_gro.c
> 
> diff --git a/app/test/meson.build b/app/test/meson.build
> index 8df8d3edd1..03bbe2be1f 100644
> --- a/app/test/meson.build
> +++ b/app/test/meson.build
> @@ -211,6 +211,7 @@ source_file_deps = {
>      'test_trace_register.c': [],
>      'test_vdev.c': ['kvargs', 'bus_vdev'],
>      'test_version.c': [],
> +    'test_gro.c':['net', 'gro'],
>  }
>  
>  source_file_ext_deps = {
> diff --git a/app/test/test_gro.c b/app/test/test_gro.c
> new file mode 100644
> index 0000000000..3bd0035e68
> --- /dev/null
> +++ b/app/test/test_gro.c
> @@ -0,0 +1,237 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2018 Intel Corporation
> + */
> +
> +#include "test.h"
> +
> +#include <rte_net.h>
> +#include <rte_gro.h>
> +
> +#define NUM_MBUFS 128
> +#define BURST 32
> +
> +/*
> + * Sample TCP/IPv4 packets from Iperf run
> + * Each packet is 132 bytes long and TCP segment is 66 bytes long
> + *
> + * 10.1.0.4:52362=>10.1.0.5:5201 Seq = 4251552885 Ack = 428268870
> + */
> +unsigned char pkts[][132] = {
> +	{
> +		0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0x7c, 0xed, 0x8d, 0xc0,
> +		0xc1, 0xf5, 0x8, 0x0, 0x45, 0x0, 0x0, 0x76, 0xa4, 0xfb, 0x40,
> +		0x0, 0x40, 0x6, 0x81, 0x7c, 0xa, 0x1, 0x0, 0x4, 0xa, 0x1, 0x0,
> +		0x5, 0xcc, 0x8a, 0x14, 0x51, 0xfd, 0x69, 0x8c, 0x75, 0x19, 0x86,
> +		0xdd, 0x46, 0x80, 0x10, 0x2, 0x0, 0x14, 0x73, 0x0, 0x0, 0x1, 0x1,
> +		0x8, 0xa, 0x3c, 0x2, 0xd1, 0xa5, 0x36, 0xb6, 0x9e, 0xda, 0x7d, 0xe9,
> +		0x63, 0xf1, 0x67, 0xeb, 0xc4, 0x93, 0xcf, 0x74, 0xcd, 0xab, 0x93,
> +		0x86, 0xe8, 0xb0, 0x1c, 0x92, 0xc8, 0x82, 0xef, 0x72, 0x34, 0xe7, 0x86,
> +		0x6d, 0xd2, 0x96, 0x8, 0x70, 0xae, 0xda, 0x60, 0xe4, 0x25, 0x39, 0xd2,
> +		0x73, 0xe7, 0xef, 0xf5, 0xf6, 0x7f, 0xbf, 0x7f, 0x5, 0x5a, 0x40, 0x6,
> +		0x65, 0x13, 0x8f, 0xa4, 0x7, 0x73, 0x41, 0xcb, 0x56, 0x3, 0x15, 0x85,
> +		0x99, 0x8c, 0xa9, 0xc8, 0x14
> +	},
> +	{
> +		0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0x7c, 0xed, 0x8d, 0xc0, 0xc1,
> +		0xf5, 0x8, 0x0, 0x45, 0x0, 0x0, 0x76, 0xa4, 0xfc, 0x40, 0x0, 0x40,
> +		0x6, 0x81, 0x7b, 0xa, 0x1, 0x0, 0x4, 0xa, 0x1, 0x0, 0x5, 0xcc, 0x8a,
> +		0x14, 0x51, 0xfd, 0x69, 0x8c, 0xb7, 0x19, 0x86, 0xdd, 0x46, 0x80, 0x10,
> +		0x2, 0x0, 0x14, 0x73, 0x0, 0x0, 0x1, 0x1, 0x8, 0xa, 0x3c, 0x2, 0xd1, 0xa5,
> +		0x36, 0xb6, 0x9e, 0xda, 0x2a, 0x6a, 0x4e, 0xf9, 0x94, 0x6, 0xaf, 0x2f, 0xeb,
> +		0xfb, 0xef, 0xa4, 0xaa, 0xe8, 0xd6, 0xc0, 0x34, 0xab, 0x8b, 0xfc, 0x14, 0xb9,
> +		0x89, 0xcb, 0xb6, 0x15, 0x58, 0xe5, 0x2a, 0x72, 0xcd, 0x1c, 0x71, 0x3, 0xf4,
> +		0xf9, 0x32, 0x7e, 0x58, 0xec, 0xe6, 0x52, 0x5a, 0x88, 0x8c, 0x24, 0x53, 0xd7,
> +		0x39, 0x80, 0xb6, 0x66, 0x9b, 0xe5, 0x45, 0xbe, 0x9, 0xf8, 0xac, 0xef, 0xc2,
> +		0x51, 0x31, 0x87, 0x9c, 0x56
> +	},
> +	{
> +		0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0x7c, 0xed, 0x8d, 0xc0, 0xc1, 0xf5, 0x8,
> +		0x0, 0x45, 0x0, 0x0, 0x76, 0xa4, 0xfd, 0x40, 0x0, 0x40, 0x6, 0x81, 0x7a, 0xa,
> +		0x1, 0x0, 0x4, 0xa, 0x1, 0x0, 0x5, 0xcc, 0x8a, 0x14, 0x51, 0xfd, 0x69, 0x8c,
> +		0xf9, 0x19, 0x86, 0xdd, 0x46, 0x80, 0x10, 0x2, 0x0, 0x14, 0x73, 0x0, 0x0, 0x1,
> +		0x1, 0x8, 0xa, 0x3c, 0x2, 0xd1, 0xa5, 0x36, 0xb6, 0x9e, 0xda, 0x68, 0x93, 0xec,
> +		0x8a, 0x35, 0xba, 0xe8, 0x24, 0x9e, 0x78, 0x6c, 0xb8, 0x65, 0xe1, 0x23, 0xc1, 0x48,
> +		0x5, 0xca, 0xea, 0x6b, 0x5, 0xe7, 0x71, 0x1a, 0x97, 0x5a, 0x23, 0xd2, 0x81, 0xc9,
> +		0x9a, 0xad, 0x1e, 0x77, 0xb1, 0x9c, 0x43, 0xf, 0xbf, 0x6c, 0xb6, 0x36, 0x46,
> +		0x99, 0xcc, 0x4, 0xf4, 0xc2, 0x87, 0x41, 0xec, 0xc6, 0xc5, 0xd9, 0x48, 0xcf,
> +		0x9b, 0xec, 0xb7, 0x2f, 0x91, 0x5f, 0x83, 0x9f, 0xd
> +	},
> +	{
> +		0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0x7c, 0xed, 0x8d, 0xc0, 0xc1, 0xf5, 0x8, 0x0,
> +		0x45, 0x0, 0x0, 0x76, 0xa4, 0xfe, 0x40, 0x0, 0x40, 0x6, 0x81, 0x79, 0xa, 0x1, 0x0,
> +		0x4, 0xa, 0x1, 0x0, 0x5, 0xcc, 0x8a, 0x14, 0x51, 0xfd, 0x69, 0x8d, 0x3b, 0x19, 0x86,
> +		0xdd, 0x46, 0x80, 0x10, 0x2, 0x0, 0x14, 0x73, 0x0, 0x0, 0x1, 0x1, 0x8, 0xa, 0x3c,
> +		0x2, 0xd1, 0xa5, 0x36, 0xb6, 0x9e, 0xda, 0xdd, 0x72, 0x54, 0xdc, 0x5, 0x51, 0xb6,
> +		0x4b, 0xdd, 0x10, 0xfb, 0x1c, 0xe8, 0x5d, 0x84, 0x75, 0xd7, 0x20, 0xd3, 0xc, 0xbd,
> +		0xba, 0x77, 0x1a, 0x14, 0x41, 0x15, 0xd0, 0x34, 0x64, 0x8d, 0x6, 0x32, 0x8f, 0x83,
> +		0x3e, 0xd6, 0xf, 0xaa, 0xe1, 0x7e, 0xdc, 0xbe, 0x33, 0x43, 0xc6, 0x38, 0xcf, 0x9b,
> +		0x6f, 0xf2, 0x1e, 0x50, 0x6f, 0xf3, 0x3b, 0x8f, 0xbf, 0x18, 0x60, 0xd5, 0x43, 0xac,
> +		0xd2, 0xbb, 0x49
> +	},
> +	{
> +		0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0x7c, 0xed, 0x8d, 0xc0, 0xc1, 0xf5, 0x8, 0x0,
> +		0x45, 0x0, 0x0, 0x76, 0xa4, 0xff, 0x40, 0x0, 0x40, 0x6, 0x81, 0x78, 0xa, 0x1, 0x0,
> +		0x4, 0xa, 0x1, 0x0, 0x5, 0xcc, 0x8a, 0x14, 0x51, 0xfd, 0x69, 0x8d, 0x7d, 0x19, 0x86,
> +		0xdd, 0x46, 0x80, 0x18, 0x2, 0x0, 0x14, 0x73, 0x0, 0x0, 0x1, 0x1, 0x8, 0xa, 0x3c,
> +		0x2, 0xd1, 0xa5, 0x36, 0xb6, 0x9e, 0xda, 0x5a, 0x95, 0x20, 0xf2, 0x20, 0x9b, 0xd,
> +		0xc1, 0x9, 0xe5, 0x3, 0x68, 0x52, 0x14, 0x2c, 0x7c, 0x98, 0x44, 0x63, 0x6c, 0xc6,
> +		0xe6, 0xba, 0x8a, 0x0, 0x10, 0x66, 0x45, 0xb1, 0xfd, 0x7b, 0x77, 0xf1, 0xf9, 0x95,
> +		0xcd, 0x7f, 0x61, 0x12, 0xeb, 0xa5, 0x23, 0xa0, 0x2, 0xe5, 0x31, 0xd8, 0x1f, 0x36,
> +		0x55, 0x59, 0x46, 0xce, 0x9f, 0xd2, 0x74, 0x6b, 0xf9, 0x63, 0xbe, 0xa1, 0xed, 0xc5,
> +		0x59, 0x22, 0x8c
> +	}
> +};

I would prefer these packets were built by the test, rather than byte arrays.
Allows for more later, and testing other cases.

> +void *gro_tcp4_ctx;
> +static struct rte_mempool *pkt_pool;
> +
> +static int test_gro_tcp4_setup(void)
> +{
> +	pkt_pool = rte_pktmbuf_pool_create("GRO_MBUF_POOL",
> +			NUM_MBUFS, BURST, 0,
> +			RTE_MBUF_DEFAULT_BUF_SIZE,
> +			SOCKET_ID_ANY);
> +	if (pkt_pool == NULL) {
> +		printf("%s: Error creating pkt mempool\n", __func__);
> +		goto failed;
> +	}
> +
> +	gro_tcp4_ctx = rte_gro_ctx_create(&(struct rte_gro_param) {
> +					.max_flow_num = 1024,
> +					.max_item_per_flow = 32,
> +					.gro_types = RTE_GRO_TCP_IPV4,
> +			});
> +	if (gro_tcp4_ctx == NULL)
> +		goto failed;
> +
> +	return TEST_SUCCESS;
> +
> +failed:
> +	if (pkt_pool)
> +		rte_mempool_free(pkt_pool);
> +	if (gro_tcp4_ctx)
> +		rte_gro_ctx_destroy(gro_tcp4_ctx);
> +
> +	pkt_pool = NULL;
> +	gro_tcp4_ctx = NULL;
> +
> +	return TEST_FAILED;
> +}
> +
> +static void test_gro_tcp4_teardown(void)
> +{
> +	if (pkt_pool)
> +		rte_mempool_free(pkt_pool);
> +	if (gro_tcp4_ctx)
> +		rte_gro_ctx_destroy(gro_tcp4_ctx);
> +	pkt_pool = NULL;
> +	gro_tcp4_ctx = NULL;
> +}
> +
> +static int testsuite_setup(void)
> +{
> +	return TEST_SUCCESS;
> +}
> +
> +static void testsuite_teardown(void)
> +{
> +}

If testsuite does not need setup/teardown those callbacks
can be left NULL. I.E no need for stubs.

> +static int32_t
> +test_gro_tcp4(void)
> +{
> +	struct rte_mbuf *pkts_mb[5];
> +	struct rte_mbuf *gro_pkts[5];
> +	int nb_pkts;
> +	int nb_gro_pkts;
> +	struct rte_net_hdr_lens hdr_lens = {0};
> +	struct rte_ether_hdr *eth_hdr;
> +	struct rte_ipv4_hdr *ipv4_hdr;
> +	struct rte_tcp_hdr *tcp_hdr;
> +	struct rte_ether_addr src_addr = {
> +		.addr_bytes = {0x7c, 0xed, 0x8d, 0xc0, 0xc1, 0xf5}
> +	};
> +	struct rte_ether_addr dst_addr = {
> +		.addr_bytes = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc}
> +	};
> +
> +	for (int i = 0; i < 5; i++) {
> +		pkts_mb[i] = rte_pktmbuf_alloc(pkt_pool);
> +		if (pkts_mb[i] == NULL)
> +			goto failed;
> +		rte_memcpy(rte_pktmbuf_mtod(pkts_mb[i], void *), pkts[i], 132);
> +		pkts_mb[i]->data_len = 132;
> +		pkts_mb[i]->pkt_len = 132;
> +		pkts_mb[i]->packet_type = rte_net_get_ptype(pkts_mb[i], &hdr_lens,
> +										RTE_PTYPE_ALL_MASK);

Better to use rte_pktmbuf_append, it will fix all the lengths for yu.

> +		pkts_mb[i]->l2_len = hdr_lens.l2_len;
> +		pkts_mb[i]->l3_len = hdr_lens.l3_len;
> +		pkts_mb[i]->l4_len = hdr_lens.l4_len;
> +	}
> +
> +	/* GRO reassemble */
> +	nb_pkts = rte_gro_reassemble(&pkts_mb[0], 5, gro_tcp4_ctx);
> +	TEST_ASSERT(nb_pkts == 0, "Not expected packets after GRO");
> +	TEST_ASSERT(rte_gro_get_pkt_count(gro_tcp4_ctx) == 1, "GRO pkt count mismatch");
> +
> +	/* GRO timeout flush */
> +	nb_gro_pkts = rte_gro_timeout_flush(gro_tcp4_ctx, 0, RTE_GRO_TCP_IPV4, gro_pkts, 5);
> +	TEST_ASSERT(nb_gro_pkts == 1, "GRO timeout flush pkt count mismatch");
> +	TEST_ASSERT(rte_gro_get_pkt_count(gro_tcp4_ctx) == 0, "GRO pkt count after flush mismatch");
> +	TEST_ASSERT(gro_pkts[0]->pkt_len == 396, "GRO merged pkt len mismatch");
> +
> +	eth_hdr = rte_pktmbuf_mtod(gro_pkts[0], struct rte_ether_hdr *);
> +	ipv4_hdr = (struct rte_ipv4_hdr *)(rte_pktmbuf_mtod(
> +					gro_pkts[0], char *) + sizeof(struct rte_ether_hdr));
> +	tcp_hdr = (struct rte_tcp_hdr *)((char *)ipv4_hdr + sizeof(struct rte_ipv4_hdr));
> +
> +	TEST_ASSERT_BUFFERS_ARE_EQUAL(eth_hdr->src_addr.addr_bytes,
> +		src_addr.addr_bytes, RTE_ETHER_ADDR_LEN, "GRO merged pkt Ethernet SRC MAC mismatch");
> +	 TEST_ASSERT_BUFFERS_ARE_EQUAL(eth_hdr->dst_addr.addr_bytes,
> +		dst_addr.addr_bytes, RTE_ETHER_ADDR_LEN, "GRO merged pkt Ethernet DST MAC mismatch");
> +
> +	TEST_ASSERT(rte_be_to_cpu_32(ipv4_hdr->src_addr) == 0x0a010004,
> +		"GRO merged pkt IP src addr mismatch");
> +	TEST_ASSERT(rte_be_to_cpu_32(ipv4_hdr->dst_addr) == 0x0a010005,
> +		"GRO merged pkt IP dst addr mismatch");
> +	TEST_ASSERT(rte_be_to_cpu_16(ipv4_hdr->packet_id) == 0xa4fb,
> +		"GRO merged pkt IP id mismatch");
> +
> +	TEST_ASSERT(rte_be_to_cpu_16(tcp_hdr->src_port) == 52362,
> +		"GRO merged pkt TCP src port mismatch");
> +	TEST_ASSERT(rte_be_to_cpu_16(tcp_hdr->dst_port) == 5201,
> +		"GRO merged pkt TCP dst port mismatch");
> +	TEST_ASSERT(rte_be_to_cpu_32(tcp_hdr->sent_seq) == 4251552885,
> +		"GRO merged pkt TCP seq num mismatch");
> +	TEST_ASSERT(rte_be_to_cpu_32(tcp_hdr->recv_ack) == 428268870,
> +		"GRO merged pkt TCP ack num mismatch");
> +
> +	return TEST_SUCCESS;
> +
> +failed:
> +	return TEST_FAILED;
> +}
> +
> +static struct unit_test_suite gro_testsuite  = {
> +	.suite_name = "GRO Unit Test Suite",
> +	.setup = testsuite_setup,
> +	.teardown = testsuite_teardown,
> +	.unit_test_cases = {
> +		TEST_CASE_ST(test_gro_tcp4_setup, test_gro_tcp4_teardown,
> +			     test_gro_tcp4),
> +
> +		TEST_CASES_END() /**< NULL terminate unit test array */
> +	}
> +};
> +
> +static int
> +test_gro(void)
> +{
> +	rte_log_set_global_level(RTE_LOG_DEBUG);
> +	rte_log_set_level(RTE_LOGTYPE_EAL, RTE_LOG_DEBUG);
> +
> +	return unit_test_suite_runner(&gro_testsuite);
> +}
> +
> +
> +REGISTER_FAST_TEST(gro_autotest, false, true, test_gro);
> diff --git a/lib/gro/gro_tcp4.c b/lib/gro/gro_tcp4.c
> index 855cc7a71d..8459037eef 100644
> --- a/lib/gro/gro_tcp4.c
> +++ b/lib/gro/gro_tcp4.c
> @@ -5,6 +5,8 @@
>  #include <rte_malloc.h>
>  #include <rte_mbuf.h>
>  #include <rte_ethdev.h>
> +#include <rte_hash.h>
> +#include <rte_jhash.h>
>  
>  #include "gro_tcp4.h"
>  #include "gro_tcp_internal.h"
> @@ -57,6 +59,15 @@ gro_tcp4_tbl_create(uint16_t socket_id,
>  		tbl->flows[i].start_index = INVALID_ARRAY_INDEX;
>  	tbl->max_flow_num = entries_num;
>  
> +	/* Create Hash table for faster lookup of the flows */
> +	tbl->flow_hash = rte_hash_create(&(struct rte_hash_parameters){
> +		.name = "gro_tcp4_flow_hash",
> +		.entries = tbl->max_flow_num,
> +		.key_len = sizeof(struct tcp4_flow_key),
> +		.hash_func = rte_jhash,
> +		.hash_func_init_val = 0
> +	});
> +
>  	return tbl;
>  }
>  
> @@ -69,6 +80,7 @@ gro_tcp4_tbl_destroy(void *tbl)
>  		rte_free(tcp_tbl->items);
>  		rte_free(tcp_tbl->flows);
>  	}
> +	rte_hash_free(tcp_tbl->flow_hash);
>  	rte_free(tcp_tbl);
>  }
>  
> @@ -91,11 +103,17 @@ insert_new_flow(struct gro_tcp4_tbl *tbl,
>  {
>  	struct tcp4_flow_key *dst;
>  	uint32_t flow_idx;
> +	int32_t ret;
>  
>  	flow_idx = find_an_empty_flow(tbl);
>  	if (unlikely(flow_idx == INVALID_ARRAY_INDEX))
>  		return INVALID_ARRAY_INDEX;
>  
> +	ret = rte_hash_add_key_data(tbl->flow_hash, src,
> +			(void *)&tbl->flows[flow_idx]);
> +	if (ret < 0)
> +		return INVALID_ARRAY_INDEX;
> +
>  	dst = &(tbl->flows[flow_idx].key);
>  
>  	ASSIGN_COMMON_TCP_KEY((&src->cmn_key), (&dst->cmn_key));
> @@ -124,9 +142,8 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt,
>  
>  	struct tcp4_flow_key key;
>  	uint32_t item_idx;
> -	uint32_t i, max_flow_num, remaining_flow_num;
> -	uint8_t find;
> -	uint32_t item_start_idx;
> +	int ret;
> +	struct gro_tcp4_flow *flow;
>  
>  	/*
>  	 * Don't process the packet whose TCP header length is greater
> @@ -173,22 +190,8 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt,
>  	is_atomic = (frag_off & RTE_IPV4_HDR_DF_FLAG) == RTE_IPV4_HDR_DF_FLAG;
>  	ip_id = is_atomic ? 0 : rte_be_to_cpu_16(ipv4_hdr->packet_id);
>  
> -	/* Search for a matched flow. */
> -	max_flow_num = tbl->max_flow_num;
> -	remaining_flow_num = tbl->flow_num;
> -	find = 0;
> -	for (i = 0; i < max_flow_num && remaining_flow_num; i++) {
> -		if (tbl->flows[i].start_index != INVALID_ARRAY_INDEX) {
> -			if (is_same_tcp4_flow(tbl->flows[i].key, key)) {
> -				find = 1;
> -				item_start_idx = tbl->flows[i].start_index;
> -				break;
> -			}
> -			remaining_flow_num--;
> -		}
> -	}
> -
> -	if (find == 1) {
> +	ret = rte_hash_lookup_data(tbl->flow_hash, &key, (void **)&flow);
> +	if (ret >= 0) {
>  		/*
>  		 * Any packet with additional flags like PSH,FIN should be processed
>  		 * and flushed immediately.
> @@ -197,9 +200,9 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt,
>  		 */
>  		if (tcp_hdr->tcp_flags & (RTE_TCP_ACK_FLAG | RTE_TCP_PSH_FLAG | RTE_TCP_FIN_FLAG)) {
>  			if (tcp_hdr->tcp_flags != RTE_TCP_ACK_FLAG)
> -				tbl->items[item_start_idx].start_time = 0;
> +				tbl->items[flow->start_index].start_time = 0;
>  			return process_tcp_item(pkt, tcp_hdr, tcp_dl, tbl->items,
> -						tbl->flows[i].start_index, &tbl->item_num,
> +						flow->start_index, &tbl->item_num,
>  						tbl->max_item_num, ip_id, is_atomic, start_time);
>  		} else {
>  			return -1;
> @@ -256,6 +259,8 @@ gro_tcp4_tbl_timeout_flush(struct gro_tcp4_tbl *tbl,
>  	uint16_t k = 0;
>  	uint32_t i, j;
>  	uint32_t max_flow_num = tbl->max_flow_num;
> +	struct gro_tcp4_flow *flow;
> +	int ret;
>  
>  	for (i = 0; i < max_flow_num; i++) {
>  		if (unlikely(tbl->flow_num == 0))
> @@ -273,9 +278,18 @@ gro_tcp4_tbl_timeout_flush(struct gro_tcp4_tbl *tbl,
>  				 */
>  				j = delete_tcp_item(tbl->items, j,
>  							&tbl->item_num, INVALID_ARRAY_INDEX);
> -				tbl->flows[i].start_index = j;
> -				if (j == INVALID_ARRAY_INDEX)
> +				if (j == INVALID_ARRAY_INDEX) {
> +					flow = &tbl->flows[i];
> +					ret = rte_hash_del_key(tbl->flow_hash, &flow->key);
> +					RTE_ASSERT(ret >= 0);
> +					if (ret >= 0) {
> +						ret = rte_hash_free_key_with_position(
> +									tbl->flow_hash, ret);
> +						RTE_ASSERT(ret == 0);
> +					}
>  					tbl->flow_num--;
> +				}
> +				tbl->flows[i].start_index = j;
>  
>  				if (unlikely(k == nb_out))
>  					return k;
> diff --git a/lib/gro/gro_tcp4.h b/lib/gro/gro_tcp4.h
> index 245e5da486..babf4f7d01 100644
> --- a/lib/gro/gro_tcp4.h
> +++ b/lib/gro/gro_tcp4.h
> @@ -33,6 +33,8 @@ struct gro_tcp4_tbl {
>  	struct gro_tcp_item *items;
>  	/* flow array */
>  	struct gro_tcp4_flow *flows;
> +	/* flow hash table */
> +	struct rte_hash *flow_hash;
>  	/* current item number */
>  	uint32_t item_num;
>  	/* current flow num */
> diff --git a/lib/gro/meson.build b/lib/gro/meson.build
> index dbce05220d..96668dcd94 100644
> --- a/lib/gro/meson.build
> +++ b/lib/gro/meson.build
> @@ -10,4 +10,4 @@ sources = files(
>          'gro_vxlan_udp4.c',
>  )
>  headers = files('rte_gro.h')
> -deps += ['ethdev']
> +deps += ['ethdev', 'hash']



More information about the dev mailing list