From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 992DE42C58; Thu, 8 Jun 2023 06:05:14 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 204CE410D3; Thu, 8 Jun 2023 06:05:14 +0200 (CEST) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by mails.dpdk.org (Postfix) with ESMTP id 409C340042 for ; Thu, 8 Jun 2023 06:05:10 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1686197111; x=1717733111; h=from:to:cc:subject:date:message-id:references: in-reply-to:content-transfer-encoding:mime-version; bh=74l9PNHbiwEHNxH65XeHlcQCRrhaMrmXmeD5xS4QrUc=; b=CaZFtQArKn2u578HI/vlUQpiuDs/8YE0znVnsjdue3NjQp3cSpvmKj2W GVdfCNbFOka5N0TSydKnJfVqPL5qwXTuhZOHdMuiYLKiw3g3uHS8k3sTX uWM4wHuQaWIqc731EidOPtPL7l51iHiL+1Rw4/1UaIEdxdgh5eTXYglC/ XzJ3ofN8ftuCgTQoMfkZ1CP7o5krpwZTquA0a8wmHaXZDM1iyiN3tPp7E UdTHvRlsLail/tmexcAX+fDTQrMz16o22fiRc/DdPICp89LOGBADO51A8 QZlGmjHP2PIxFdEP1eWjni5YoyH4rnCOdt7t9sFwFYczQkPmFUxO8alMj w==; X-IronPort-AV: E=McAfee;i="6600,9927,10734"; a="360524175" X-IronPort-AV: E=Sophos;i="6.00,226,1681196400"; d="scan'208";a="360524175" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Jun 2023 21:05:09 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10734"; a="854176830" X-IronPort-AV: E=Sophos;i="6.00,226,1681196400"; d="scan'208";a="854176830" Received: from orsmsx603.amr.corp.intel.com ([10.22.229.16]) by fmsmga001.fm.intel.com with ESMTP; 07 Jun 2023 21:05:09 -0700 Received: from orsmsx611.amr.corp.intel.com (10.22.229.24) by ORSMSX603.amr.corp.intel.com (10.22.229.16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.23; Wed, 7 Jun 2023 21:05:08 -0700 Received: from orsmsx610.amr.corp.intel.com (10.22.229.23) by ORSMSX611.amr.corp.intel.com (10.22.229.24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.23; Wed, 7 Jun 2023 21:05:08 -0700 Received: from orsedg603.ED.cps.intel.com (10.7.248.4) by orsmsx610.amr.corp.intel.com (10.22.229.23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.23 via Frontend Transport; Wed, 7 Jun 2023 21:05:08 -0700 Received: from NAM10-MW2-obe.outbound.protection.outlook.com (104.47.55.104) by edgegateway.intel.com (134.134.137.100) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2507.23; Wed, 7 Jun 2023 21:05:08 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=QHs2t7TAKMYcPpmf52lBEXOauZ3vIbFTtTtcHT5IqEKQ7dySULn7FiVwPIgj4D1sC+JfOMMnuOl1s4UgWngKzCvfBrjN7uSAP4+EAIjE1M2qeHJGmMJDO1nukN78Sn0KtuNxA3EEom4Fq6mlR/tWZ6U7Wq7Na+dK48qgOGtLrsQFa1mdaNjCZyppsVgelQjmGrLS2rWoJ1BGvIhlZ7VD72mS7vdgLgIEO7oPwrHN/SBL/St9cNBOwHrUzlLXd2BtFXS8WqY89IMrt7MwYYItZVW38BYjil5uVFOAGsT4YRb+LKhYp96xv6+vFkXElpLkhyOEgMwP8cCynJtReNr3tw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=9wSbRG9+h24uX/RE1/v3G7DtC4ThMEoiITBtSYRFQe0=; b=Ri95fX9Aonm1rKz3n0n6rHAejiWWKTb9y3RFr6wJyLevLrBKoDaDEZb7CR1TTpdHMZxvIPNJnzgWtGLOu1n61ghvCke4SJAINEAJ/AXMFUHMljm0V4gWHCr/hH2pEPCqbdCaBryDY0hSoRDzNln3feDRVBYiF6bLp77ZagmRO9zrlSkfXSKzlzQxI3GXqJPw9qsikbwiy1VjXg5LrnWrML9PqU5TfQnvqYSJ2te2NFdNp06nxHqq36VyIWR+gLp7kpH1h0Y2qafQRelmeOYADw5ZJPsjANO8hKfIdY2S6WisnNw7bsFEAQyoV9PYVus7crUAHcgHmGUmSLKF8gjmoQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=intel.com; dmarc=pass action=none header.from=intel.com; dkim=pass header.d=intel.com; arc=none Received: from CY5PR11MB6487.namprd11.prod.outlook.com (2603:10b6:930:31::17) by SJ0PR11MB5101.namprd11.prod.outlook.com (2603:10b6:a03:2dc::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6455.33; Thu, 8 Jun 2023 04:05:06 +0000 Received: from CY5PR11MB6487.namprd11.prod.outlook.com ([fe80::bbdd:44b6:dd11:5070]) by CY5PR11MB6487.namprd11.prod.outlook.com ([fe80::bbdd:44b6:dd11:5070%4]) with mapi id 15.20.6455.034; Thu, 8 Jun 2023 04:05:06 +0000 From: "Hu, Jiayu" To: Kumara Parameshwaran CC: "dev@dpdk.org" Subject: RE: [PATCH v4] gro : ipv6 changes to support GRO for TCP/ipv6 Thread-Topic: [PATCH v4] gro : ipv6 changes to support GRO for TCP/ipv6 Thread-Index: AQHZmIdczS5iBYQvv0uyxHz+IKTIRq+AQzIg Date: Thu, 8 Jun 2023 04:05:06 +0000 Message-ID: References: <20221020181425.48006-1-kumaraparmesh92@gmail.com> <20230606145802.53671-1-kumaraparamesh92@gmail.com> In-Reply-To: <20230606145802.53671-1-kumaraparamesh92@gmail.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=intel.com; x-ms-publictraffictype: Email x-ms-traffictypediagnostic: CY5PR11MB6487:EE_|SJ0PR11MB5101:EE_ x-ms-office365-filtering-correlation-id: f50e0b70-33db-4e3e-938f-08db67d58b25 x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: dlNh314w0FcKSd7stEoczsBMJdFybIRaXQmTC1Rtwn/Nq0KGX/N0dMpaPZhdiJmlTIhV1O10T75a/r7KVwu2C0qLDIjsVQm9+s+JIKK9ne8jv1nug/x/ISgrVX8u7tgS+aUX46r+c8xq46a38/NtnipFZCYbSLxbaXDIbyaeyTudgn2cm0WOd0UZxA5GSNOVbRIWRYoH8PK/lKBxXxa3aMX3BDHXEtt5V6O/o/35EH3KTRKgYBJ+OGYf9ijcOxhkw30ejhtTDAE6vRlMtH3go2wipofNFC+Nk6fbr5D+eXlVeXKLmREVdqKglVB/nycBPJxEilZmCj4XfHgQOLbCmdhYF6GHgJsx1nWsS6QnAed+RxFwE1rPFCCpkbxMjDbvMSggS63c8OW4kvxWKTwbufg8KIBhzmlYDzXJTylkxjl6IJ163I+j4e3aD78CjDxdO46UArWxIX9XlXJOc4FeCFiBp4C25sjyVrN1OwJ07IMsDpuzbp+dkJPU/6EgQuMOU2wuu/wSWAKDOwpNaoHbJyKp47KBQBxLRuI62JGHL8Le5w+VhaZ4Rb45eLgCF6VfaSav2JlqnUw+NEjimwTGiChzEz2tCwHp7W04r4IARze11SQcu7g6edhd1VLzHEKl x-forefront-antispam-report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:CY5PR11MB6487.namprd11.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230028)(346002)(136003)(376002)(396003)(39860400002)(366004)(451199021)(478600001)(30864003)(2906002)(38070700005)(6506007)(26005)(33656002)(53546011)(186003)(9686003)(83380400001)(86362001)(82960400001)(122000001)(55016003)(38100700002)(7696005)(5660300002)(52536014)(71200400001)(8936002)(8676002)(41300700001)(316002)(76116006)(64756008)(6916009)(66946007)(4326008)(66476007)(66556008)(66446008)(579004); DIR:OUT; SFP:1102; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?OcVyZTPKpnPdan1eQqKQyy+6dyWz05CpWBzvpOq28s7BUL+MwARhhUCJqClF?= =?us-ascii?Q?2b9C52xFe49jW7joxcpfclnB7FtV77RI1MiiryXh0/cmLfaAOtSkFtXcNcrv?= =?us-ascii?Q?TktD9BENxPDaaLs5tnbLtvdBj1pWL/4auNG2jFCi7SdqrY+nrIGjvbTP1/Zf?= =?us-ascii?Q?El7VyfBlqIhYVitXuOk4YA5PIYtU1oHB83LZS3HpGKOPhDc/WjtaQ8LoOz3I?= =?us-ascii?Q?Y/juU7sP0ybSz34lGCqGlJaVBxWDeUR51IwI4GmXptH2W5v6aURsaRLjfTlz?= =?us-ascii?Q?H5L2Wq+3KonXEgkORkPdgGwoZnieBVKVecg7IbH9rdC3Z6MVjoPSfkts1Pji?= =?us-ascii?Q?woYaar4LLfN9rGoXXcSLMVIYROPEpL6pdyZ4mGKuSz20r/3NxvSrNwAmVJFT?= =?us-ascii?Q?sEymeRoqC+EjHogdvQ7Y82si/8aqGLSn2pFC7VtxqAKOBBZerOAkoXdAC6u7?= =?us-ascii?Q?aQJJHBnTVhipdKD9dTQw0uGsPclCr/8pMBi1GAkZR4HNNlXiN+/noa9g3IfP?= =?us-ascii?Q?rq0BsacU8qD9/8wVlNZ4INum8sg+a2PNeOCNrhEvZ9PPwcdNz8OXZv4R10L9?= =?us-ascii?Q?z+NbGyrFXRIENN/ZBhbeKZ+eR6NRPAzswxrb+HGG/uuvf4eEt1ui5KRowC9H?= =?us-ascii?Q?g1nb4Ets/lH4KeRaGlz+j1S+y6PI033wuT9A4wvlCwm3kK5LP/Uyz299hoMc?= =?us-ascii?Q?UVvQTwi9kmAlpGX+m6iJuSoKDvM1HVbsZUNZBqhHWozHkDJIP74Y9wPFOYbb?= =?us-ascii?Q?998uc/h5fo0YAzeeCujNodQAY95mdhHrPbnKpSzYu+Mu1jef3RIxf3vr8OrC?= =?us-ascii?Q?Q3n1SUuTEaVao+UfjDwefa7/lPDAeeW3l5SGgGTr6O6hRQ3sNV/1mEpQxoQL?= =?us-ascii?Q?+/cm1x8l71rOKHrVGSEYNZ0sfiJJQxrKwcCPc0ho0IxwUdzZksr32zL5kP71?= =?us-ascii?Q?PDoMgCuM93Ua7I+tnVYxhNcnKz0T9I4kSOYoalSeB5pPko5rkJIDo7e2HSSK?= =?us-ascii?Q?h8DI3sA0l68W9YVB2Hsr12YgUPzhjt2d1QWWCOLzFVI5loaa2HI/9y1HARoS?= =?us-ascii?Q?BmxnKnOyALc3IH2HJC5ugCAU2boYC6d4yoeU9sEbXtckCIVm6M5TzjATdNn/?= =?us-ascii?Q?/vOA33djKZ4uTnbjVK1TvpPlSfQpmT0zs2fhlYWH+FR3QvnQ9afx8QiBaIuw?= =?us-ascii?Q?m0WKiKPvFjGX/rqHHyGOHT0oSJJZu+GpXDONMqWti9Ga0nqXgKUF7x/r3WnP?= =?us-ascii?Q?xaaD3rQ+/NqCdjpcRixC44MKXRxZ9sBmfNXyp8fpDE67JcOmQ/V8GNYg0sYe?= =?us-ascii?Q?JFpyVLGRCoHuEKxvwEjgVAICnvaW241u10Hem4lTDOblTMmganuh8jQFcKNZ?= =?us-ascii?Q?MyrdDVq5q7QxY+D03PeeChgpRWUCYCFA/XEKpnoAqsHPkzSjkxyo77k3DHtL?= =?us-ascii?Q?9K14BEqtMvYLuQLw2SDnal7MKHvF3ST1Bu9MJxkKI9ganWv13DKXQNGXlTA4?= =?us-ascii?Q?NNr2FwIGlVKCfQl8qHcGkUP9zKn/FF5NaxEGywwBL+qPXjl7NvGVQotSlVGS?= =?us-ascii?Q?H9PfZl120/u7jshPYL2K8FdUzCwCFJR/rb5hS4vI?= Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: CY5PR11MB6487.namprd11.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: f50e0b70-33db-4e3e-938f-08db67d58b25 X-MS-Exchange-CrossTenant-originalarrivaltime: 08 Jun 2023 04:05:06.2879 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 46c98d88-e344-4ed4-8496-4ed7712e255d X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: RYqG+/+NHtrJ6ZALwOrqQymsLaK7k2KvMEqmk21ZcspwLDHLO8G4pOHsFi68bckljTK25gghPXCjqZorM0IONw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SJ0PR11MB5101 X-OriginatorOrg: intel.com X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Hi Kumara, Please see replies inline. In addition, you need to update the programmer guide in generic_receive_off= load_lib.rst, and release note release_23_07.rst. Thanks, Jiayu > -----Original Message----- > From: Kumara Parameshwaran > Sent: Tuesday, June 6, 2023 10:58 PM > To: Hu, Jiayu > Cc: dev@dpdk.org; Kumara Parameshwaran > > Subject: [PATCH v4] gro : ipv6 changes to support GRO for TCP/ipv6 >=20 > The patch adds GRO support for TCP/ipv6 packets. This does not include th= e > support for vxlan, udp ipv6 packets. >=20 > Signed-off-by: Kumara Parameshwaran >=20 > diff --git a/lib/gro/gro_tcp.c b/lib/gro/gro_tcp.c new file mode 100644 i= ndex > 0000000000..02a7d0f8c5 > --- /dev/null > +++ b/lib/gro/gro_tcp.c For gro_tcp.c and gro_tcp.h, it's better to add "_internal" in the file nam= e. > @@ -0,0 +1,128 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2017 Intel Corporation > + */ > +#include > +#include > +#include > + > +#include "gro_tcp.h" > + > +static inline uint32_t > +find_an_empty_item(struct gro_tcp_item *items, > + uint32_t max_item_num) > +{ > + uint32_t i; > + > + for (i =3D 0; i < max_item_num; i++) > + if (items[i].firstseg =3D=3D NULL) > + return i; > + return INVALID_ARRAY_INDEX; > +} > + > +uint32_t > +insert_new_tcp_item(struct rte_mbuf *pkt, > + struct gro_tcp_item *items, > + uint32_t *item_num, > + uint32_t max_item_num, > + uint64_t start_time, > + uint32_t prev_idx, > + uint32_t sent_seq, > + uint16_t ip_id, > + uint8_t is_atomic) This function can be inline. > +{ > + uint32_t item_idx; > + > + item_idx =3D find_an_empty_item(items, max_item_num); > + if (item_idx =3D=3D INVALID_ARRAY_INDEX) > + return INVALID_ARRAY_INDEX; > + > + items[item_idx].firstseg =3D pkt; > + items[item_idx].lastseg =3D rte_pktmbuf_lastseg(pkt); > + items[item_idx].start_time =3D start_time; > + items[item_idx].next_pkt_idx =3D INVALID_ARRAY_INDEX; > + items[item_idx].sent_seq =3D sent_seq; > + items[item_idx].ip_id =3D ip_id; > + items[item_idx].nb_merged =3D 1; > + items[item_idx].is_atomic =3D is_atomic; > + (*item_num) +=3D 1; > + > + /* if the previous packet exists, chain them together. */ > + if (prev_idx !=3D INVALID_ARRAY_INDEX) { > + items[item_idx].next_pkt_idx =3D > + items[prev_idx].next_pkt_idx; > + items[prev_idx].next_pkt_idx =3D item_idx; > + } > + > + return item_idx; > +} > + > +uint32_t > +delete_tcp_item(struct gro_tcp_item *items, uint32_t item_idx, > + uint32_t *item_num, > + uint32_t prev_item_idx) > +{ > + uint32_t next_idx =3D items[item_idx].next_pkt_idx; > + > + /* NULL indicates an empty item */ > + items[item_idx].firstseg =3D NULL; > + (*item_num) -=3D 1; > + if (prev_item_idx !=3D INVALID_ARRAY_INDEX) > + items[prev_item_idx].next_pkt_idx =3D next_idx; > + > + return next_idx; > +} This function can be inline. > + > +int32_t > +gro_process_tcp_item(struct rte_mbuf *pkt, > + struct rte_tcp_hdr *tcp_hdr, > + int32_t tcp_dl, > + struct gro_tcp_item *items, > + uint32_t item_idx, > + uint32_t *item_num, > + uint32_t max_item_num, > + uint16_t ip_id, > + uint8_t is_atomic, > + uint64_t start_time) It is for internal use, so it's better to remove "gro_" from the function n= ame. > +{ > + uint32_t cur_idx; > + uint32_t prev_idx; > + int cmp; > + uint32_t sent_seq; > + > + sent_seq =3D rte_be_to_cpu_32(tcp_hdr->sent_seq); > + /* > + * Check all packets in the flow and try to find a neighbor for > + * the input packet. > + */ > + cur_idx =3D item_idx; > + prev_idx =3D cur_idx; > + do { > + cmp =3D check_seq_option(&items[cur_idx], tcp_hdr, > + sent_seq, ip_id, pkt->l4_len, tcp_dl, 0, > + is_atomic); > + if (cmp) { > + if (merge_two_tcp_packets(&items[cur_idx], > + pkt, cmp, sent_seq, ip_id, 0)) > + return 1; > + /* > + * Fail to merge the two packets, as the packet > + * length is greater than the max value. Store > + * the packet into the flow. > + */ > + if (insert_new_tcp_item(pkt, items, item_num, > max_item_num, start_time, cur_idx, > + sent_seq, ip_id, is_atomic) =3D=3D > + INVALID_ARRAY_INDEX) > + return -1; > + return 0; > + } > + prev_idx =3D cur_idx; > + cur_idx =3D items[cur_idx].next_pkt_idx; > + } while (cur_idx !=3D INVALID_ARRAY_INDEX); > + > + /* Fail to find a neighbor, so store the packet into the flow. */ > + if (insert_new_tcp_item(pkt, items, item_num, max_item_num, > start_time, prev_idx, sent_seq, > + ip_id, is_atomic) =3D=3D INVALID_ARRAY_INDEX) > + return -1; > + > + return 0; > +} > diff --git a/lib/gro/gro_tcp.h b/lib/gro/gro_tcp.h new file mode 100644 i= ndex > 0000000000..4b5b4eda9c > --- /dev/null > +++ b/lib/gro/gro_tcp.h > @@ -0,0 +1,209 @@ > +#ifndef _GRO_TCP_H_ > +#define _GRO_TCP_H_ > + > +#define INVALID_ARRAY_INDEX 0xffffffffUL > + > +#include > + > +/* > + * The max length of a IPv4 packet, which includes the length of the L3 > + * header, the L4 header and the data payload. > + */ > +#define MAX_IP_PKT_LENGTH UINT16_MAX > + > +/* The maximum TCP header length */ > +#define MAX_TCP_HLEN 60 > +#define INVALID_TCP_HDRLEN(len) \ > + (((len) < sizeof(struct rte_tcp_hdr)) || ((len) > MAX_TCP_HLEN)) > + > +struct gro_tcp_flow { This structure name is confusing. In the upper layer, tcp4 and tcp6 have gr= o_tcp4_flow and gro_tcp6_flow, which represent a flow. Inside gro_tcp4/6_flow, there ar= e keys, represented by struct tcp4/6_flow_key. But inside struct tcp4/6_flow_key, t= here is struct gro_tcp_flow. Need to rename struct gro_tcp_flow, like common_tcp_fl= ow_key. > + struct rte_ether_addr eth_saddr; > + struct rte_ether_addr eth_daddr; > + uint32_t recv_ack; > + uint16_t src_port; > + uint16_t dst_port; > +}; > + > +#define ASSIGN_TCP_FLOW_KEY(k1, k2) \ Ditto. The macro needs rename, like ASSIGN_COMMON_TCP_FLOW_KEY. > + do {\ > + rte_ether_addr_copy(&(k1->eth_saddr), &(k2->eth_saddr)); \ > + rte_ether_addr_copy(&(k1->eth_daddr), &(k2->eth_daddr)); > \ > + k2->recv_ack =3D k1->recv_ack; \ > + k2->src_port =3D k1->src_port; \ > + k2->dst_port =3D k1->dst_port; \ > + } while (0) > + > +struct gro_tcp_item { > + /* > + * The first MBUF segment of the packet. If the value > + * is NULL, it means the item is empty. > + */ > + struct rte_mbuf *firstseg; > + /* The last MBUF segment of the packet */ > + struct rte_mbuf *lastseg; > + /* > + * The time when the first packet is inserted into the table. > + * This value won't be updated, even if the packet is merged > + * with other packets. > + */ > + uint64_t start_time; > + /* > + * next_pkt_idx is used to chain the packets that > + * are in the same flow but can't be merged together > + * (e.g. caused by packet reordering). > + */ > + uint32_t next_pkt_idx; > + /* TCP sequence number of the packet */ > + uint32_t sent_seq; > + /* IPv4 ID of the packet */ > + uint16_t ip_id; The ip_id field is not used by tcp6. It's better to use an union to include= ip_id for IPv4 and an useless member for IPv6 with some comments to avoid confusing. > + /* the number of merged packets */ > + uint16_t nb_merged; > + /* Indicate if IPv4 ID can be ignored */ > + uint8_t is_atomic; > +}; > + > +uint32_t > +insert_new_tcp_item(struct rte_mbuf *pkt, > + struct gro_tcp_item *items, > + uint32_t *item_num, > + uint32_t table_size, > + uint64_t start_time, > + uint32_t prev_idx, > + uint32_t sent_seq, > + uint16_t ip_id, > + uint8_t is_atomic); > + > +uint32_t > +delete_tcp_item(struct gro_tcp_item *items, > + uint32_t item_idx, > + uint32_t *item_num, > + uint32_t prev_item_idx); > + > +int32_t > +gro_process_tcp_item(struct rte_mbuf *pkt, > + struct rte_tcp_hdr *tcp_hdr, > + int32_t tcp_dl, > + struct gro_tcp_item *items, > + uint32_t item_idx, > + uint32_t *item_num, > + uint32_t table_size, > + uint16_t ip_id, > + uint8_t is_atomic, > + uint64_t start_time); > + > +/* > + * Merge two TCP packets without updating checksums. > + * If cmp is larger than 0, append the new packet to the > + * original packet. Otherwise, pre-pend the new packet to > + * the original packet. > + */ > +static inline int > +merge_two_tcp_packets(struct gro_tcp_item *item, > + struct rte_mbuf *pkt, > + int cmp, > + uint32_t sent_seq, > + uint16_t ip_id, > + uint16_t l2_offset) > +{ > + struct rte_mbuf *pkt_head, *pkt_tail, *lastseg; > + uint16_t hdr_len, l2_len; > + > + if (cmp > 0) { > + pkt_head =3D item->firstseg; > + pkt_tail =3D pkt; > + } else { > + pkt_head =3D pkt; > + pkt_tail =3D item->firstseg; > + } > + > + /* check if the IPv4 packet length is greater than the max value */ > + hdr_len =3D l2_offset + pkt_head->l2_len + pkt_head->l3_len + > + pkt_head->l4_len; > + l2_len =3D l2_offset > 0 ? pkt_head->outer_l2_len : pkt_head->l2_len; > + if (unlikely(pkt_head->pkt_len - l2_len + pkt_tail->pkt_len - > + hdr_len > MAX_IP_PKT_LENGTH)) > + return 0; > + > + /* remove the packet header for the tail packet */ > + rte_pktmbuf_adj(pkt_tail, hdr_len); > + > + /* chain two packets together */ > + if (cmp > 0) { > + item->lastseg->next =3D pkt; > + item->lastseg =3D rte_pktmbuf_lastseg(pkt); > + /* update IP ID to the larger value */ > + item->ip_id =3D ip_id; > + } else { > + lastseg =3D rte_pktmbuf_lastseg(pkt); > + lastseg->next =3D item->firstseg; > + item->firstseg =3D pkt; > + /* update sent_seq to the smaller value */ > + item->sent_seq =3D sent_seq; > + item->ip_id =3D ip_id; > + } > + item->nb_merged++; > + > + /* update MBUF metadata for the merged packet */ > + pkt_head->nb_segs +=3D pkt_tail->nb_segs; > + pkt_head->pkt_len +=3D pkt_tail->pkt_len; > + > + return 1; > +} > + > +/* > + * Check if two TCP/IPv4 packets are neighbors. > + */ > +static inline int > +check_seq_option(struct gro_tcp_item *item, > + struct rte_tcp_hdr *tcph, > + uint32_t sent_seq, > + uint16_t ip_id, > + uint16_t tcp_hl, > + uint16_t tcp_dl, > + uint16_t l2_offset, > + uint8_t is_atomic) > +{ > + struct rte_mbuf *pkt_orig =3D item->firstseg; > + char *iph_orig; > + struct rte_tcp_hdr *tcph_orig; > + uint16_t len, tcp_hl_orig; > + > + iph_orig =3D (char *)(rte_pktmbuf_mtod(pkt_orig, char *) + > + l2_offset + pkt_orig->l2_len); > + tcph_orig =3D (struct rte_tcp_hdr *)(iph_orig + pkt_orig->l3_len); > + tcp_hl_orig =3D pkt_orig->l4_len; > + > + /* Check if TCP option fields equal */ > + len =3D RTE_MAX(tcp_hl, tcp_hl_orig) - sizeof(struct rte_tcp_hdr); > + if ((tcp_hl !=3D tcp_hl_orig) || ((len > 0) && > + (memcmp(tcph + 1, tcph_orig + 1, > + len) !=3D 0))) > + return 0; > + > + /* Don't merge packets whose DF bits are different */ > + if (unlikely(item->is_atomic ^ is_atomic)) > + return 0; > + > + /* check if the two packets are neighbors */ > + len =3D pkt_orig->pkt_len - l2_offset - pkt_orig->l2_len - > + pkt_orig->l3_len - tcp_hl_orig; > + if ((sent_seq =3D=3D item->sent_seq + len) && (is_atomic || > + (ip_id =3D=3D item->ip_id + 1))) > + /* append the new packet */ > + return 1; > + else if ((sent_seq + tcp_dl =3D=3D item->sent_seq) && (is_atomic || > + (ip_id + item->nb_merged =3D=3D item->ip_id))) > + /* pre-pend the new packet */ > + return -1; > + > + return 0; > +} > + > +static inline int > +is_same_tcp_flow(struct gro_tcp_flow *k1, struct gro_tcp_flow *k2) { > + return (!memcmp(k1, k2, sizeof(struct gro_tcp_flow))); } I think this function needs rename, as the result of this function cannot i= dentify if they are=20 same TCP flow. > + > +#endif > diff --git a/lib/gro/gro_tcp4.c b/lib/gro/gro_tcp4.c index > 0014096e63..ffc33747c4 100644 > --- a/lib/gro/gro_tcp4.c > +++ b/lib/gro/gro_tcp4.c > @@ -7,6 +7,7 @@ > #include >=20 > #include "gro_tcp4.h" > +#include "gro_tcp.h" >=20 > void * > gro_tcp4_tbl_create(uint16_t socket_id, @@ -30,7 +31,7 @@ > gro_tcp4_tbl_create(uint16_t socket_id, > if (tbl =3D=3D NULL) > return NULL; >=20 > - size =3D sizeof(struct gro_tcp4_item) * entries_num; > + size =3D sizeof(struct gro_tcp_item) * entries_num; > tbl->items =3D rte_zmalloc_socket(__func__, > size, > RTE_CACHE_LINE_SIZE, > @@ -71,18 +72,6 @@ gro_tcp4_tbl_destroy(void *tbl) > rte_free(tcp_tbl); > } >=20 > -static inline uint32_t > -find_an_empty_item(struct gro_tcp4_tbl *tbl) -{ > - uint32_t i; > - uint32_t max_item_num =3D tbl->max_item_num; > - > - for (i =3D 0; i < max_item_num; i++) > - if (tbl->items[i].firstseg =3D=3D NULL) > - return i; > - return INVALID_ARRAY_INDEX; > -} > - > static inline uint32_t > find_an_empty_flow(struct gro_tcp4_tbl *tbl) { @@ -95,56 +84,6 @@ > find_an_empty_flow(struct gro_tcp4_tbl *tbl) > return INVALID_ARRAY_INDEX; > } >=20 > -static inline uint32_t > -insert_new_item(struct gro_tcp4_tbl *tbl, > - struct rte_mbuf *pkt, > - uint64_t start_time, > - uint32_t prev_idx, > - uint32_t sent_seq, > - uint16_t ip_id, > - uint8_t is_atomic) > -{ > - uint32_t item_idx; > - > - item_idx =3D find_an_empty_item(tbl); > - if (item_idx =3D=3D INVALID_ARRAY_INDEX) > - return INVALID_ARRAY_INDEX; > - > - tbl->items[item_idx].firstseg =3D pkt; > - tbl->items[item_idx].lastseg =3D rte_pktmbuf_lastseg(pkt); > - tbl->items[item_idx].start_time =3D start_time; > - tbl->items[item_idx].next_pkt_idx =3D INVALID_ARRAY_INDEX; > - tbl->items[item_idx].sent_seq =3D sent_seq; > - tbl->items[item_idx].ip_id =3D ip_id; > - tbl->items[item_idx].nb_merged =3D 1; > - tbl->items[item_idx].is_atomic =3D is_atomic; > - tbl->item_num++; > - > - /* if the previous packet exists, chain them together. */ > - if (prev_idx !=3D INVALID_ARRAY_INDEX) { > - tbl->items[item_idx].next_pkt_idx =3D > - tbl->items[prev_idx].next_pkt_idx; > - tbl->items[prev_idx].next_pkt_idx =3D item_idx; > - } > - > - return item_idx; > -} > - > -static inline uint32_t > -delete_item(struct gro_tcp4_tbl *tbl, uint32_t item_idx, > - uint32_t prev_item_idx) > -{ > - uint32_t next_idx =3D tbl->items[item_idx].next_pkt_idx; > - > - /* NULL indicates an empty item */ > - tbl->items[item_idx].firstseg =3D NULL; > - tbl->item_num--; > - if (prev_item_idx !=3D INVALID_ARRAY_INDEX) > - tbl->items[prev_item_idx].next_pkt_idx =3D next_idx; > - > - return next_idx; > -} > - > static inline uint32_t > insert_new_flow(struct gro_tcp4_tbl *tbl, > struct tcp4_flow_key *src, > @@ -159,13 +98,10 @@ insert_new_flow(struct gro_tcp4_tbl *tbl, >=20 > dst =3D &(tbl->flows[flow_idx].key); >=20 > - rte_ether_addr_copy(&(src->eth_saddr), &(dst->eth_saddr)); > - rte_ether_addr_copy(&(src->eth_daddr), &(dst->eth_daddr)); > + ASSIGN_TCP_FLOW_KEY((&src->tcp_flow), (&dst->tcp_flow)); > + > dst->ip_src_addr =3D src->ip_src_addr; > dst->ip_dst_addr =3D src->ip_dst_addr; > - dst->recv_ack =3D src->recv_ack; > - dst->src_port =3D src->src_port; > - dst->dst_port =3D src->dst_port; >=20 > tbl->flows[flow_idx].start_index =3D item_idx; > tbl->flow_num++; > @@ -173,21 +109,6 @@ insert_new_flow(struct gro_tcp4_tbl *tbl, > return flow_idx; > } >=20 > -/* > - * update the packet length for the flushed packet. > - */ > -static inline void > -update_header(struct gro_tcp4_item *item) -{ > - struct rte_ipv4_hdr *ipv4_hdr; > - struct rte_mbuf *pkt =3D item->firstseg; > - > - ipv4_hdr =3D (struct rte_ipv4_hdr *)(rte_pktmbuf_mtod(pkt, char *) + > - pkt->l2_len); > - ipv4_hdr->total_length =3D rte_cpu_to_be_16(pkt->pkt_len - > - pkt->l2_len); > -} > - > int32_t > gro_tcp4_reassemble(struct rte_mbuf *pkt, > struct gro_tcp4_tbl *tbl, > @@ -195,16 +116,15 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt, { > struct rte_ether_hdr *eth_hdr; > struct rte_ipv4_hdr *ipv4_hdr; > - struct rte_tcp_hdr *tcp_hdr; > - uint32_t sent_seq; > int32_t tcp_dl; > + struct rte_tcp_hdr *tcp_hdr; > uint16_t ip_id, hdr_len, frag_off, ip_tlen; > uint8_t is_atomic; > + uint32_t sent_seq; No need to change tcp_hdr and sent_seq here. >=20 > struct tcp4_flow_key key; > - uint32_t cur_idx, prev_idx, item_idx; > + uint32_t item_idx; > uint32_t i, max_flow_num, remaining_flow_num; > - int cmp; > uint8_t find; >=20 > /* > @@ -216,7 +136,7 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt, >=20 > eth_hdr =3D rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *); > ipv4_hdr =3D (struct rte_ipv4_hdr *)((char *)eth_hdr + pkt->l2_len); > - tcp_hdr =3D (struct rte_tcp_hdr *)((char *)ipv4_hdr + pkt->l3_len); > + tcp_hdr =3D rte_pktmbuf_mtod_offset(pkt, struct rte_tcp_hdr *, > +pkt->l2_len + pkt->l3_len); > hdr_len =3D pkt->l2_len + pkt->l3_len + pkt->l4_len; >=20 > /* > @@ -230,7 +150,6 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt, > ip_tlen =3D rte_be_to_cpu_16(ipv4_hdr->total_length); > if (pkt->pkt_len > (uint32_t)(ip_tlen + pkt->l2_len)) > rte_pktmbuf_trim(pkt, pkt->pkt_len - ip_tlen - pkt->l2_len); > - > /* > * Don't process the packet whose payload length is less than or > * equal to 0. > @@ -239,6 +158,13 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt, > if (tcp_dl <=3D 0) > return -1; >=20 > + rte_ether_addr_copy(&(eth_hdr->src_addr), > &(key.tcp_flow.eth_saddr)); > + rte_ether_addr_copy(&(eth_hdr->dst_addr), > &(key.tcp_flow.eth_daddr)); > + key.ip_src_addr =3D ipv4_hdr->src_addr; > + key.ip_dst_addr =3D ipv4_hdr->dst_addr; > + key.tcp_flow.src_port =3D tcp_hdr->src_port; > + key.tcp_flow.dst_port =3D tcp_hdr->dst_port; > + key.tcp_flow.recv_ack =3D tcp_hdr->recv_ack; > /* > * Save IPv4 ID for the packet whose DF bit is 0. For the packet > * whose DF bit is 1, IPv4 ID is ignored. > @@ -246,15 +172,6 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt, > frag_off =3D rte_be_to_cpu_16(ipv4_hdr->fragment_offset); > is_atomic =3D (frag_off & RTE_IPV4_HDR_DF_FLAG) =3D=3D > RTE_IPV4_HDR_DF_FLAG; > ip_id =3D is_atomic ? 0 : rte_be_to_cpu_16(ipv4_hdr->packet_id); > - sent_seq =3D rte_be_to_cpu_32(tcp_hdr->sent_seq); > - > - rte_ether_addr_copy(&(eth_hdr->src_addr), &(key.eth_saddr)); > - rte_ether_addr_copy(&(eth_hdr->dst_addr), &(key.eth_daddr)); > - key.ip_src_addr =3D ipv4_hdr->src_addr; > - key.ip_dst_addr =3D ipv4_hdr->dst_addr; > - key.src_port =3D tcp_hdr->src_port; > - key.dst_port =3D tcp_hdr->dst_port; > - key.recv_ack =3D tcp_hdr->recv_ack; >=20 > /* Search for a matched flow. */ > max_flow_num =3D tbl->max_flow_num; > @@ -270,63 +187,44 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt, > } > } >=20 > - /* > - * Fail to find a matched flow. Insert a new flow and store the > - * packet into the flow. > - */ > if (find =3D=3D 0) { > - item_idx =3D insert_new_item(tbl, pkt, start_time, > - INVALID_ARRAY_INDEX, sent_seq, ip_id, > - is_atomic); > + sent_seq =3D rte_be_to_cpu_32(tcp_hdr->sent_seq); > + item_idx =3D insert_new_tcp_item(pkt, tbl->items, &tbl- > >item_num, tbl->max_item_num, start_time, > + INVALID_ARRAY_INDEX, > sent_seq, ip_id, > + is_atomic); > if (item_idx =3D=3D INVALID_ARRAY_INDEX) > return -1; > if (insert_new_flow(tbl, &key, item_idx) =3D=3D > - INVALID_ARRAY_INDEX) { > + INVALID_ARRAY_INDEX) { > /* > * Fail to insert a new flow, so delete the > * stored packet. > - */ > - delete_item(tbl, item_idx, INVALID_ARRAY_INDEX); > + */ > + delete_tcp_item(tbl->items, item_idx, &tbl- > >item_num, > +INVALID_ARRAY_INDEX); > return -1; > } > return 0; > } > + item_idx =3D tbl->flows[i].start_index; No need to update item_idx, and you can directly pass tbl->flows[i].start_i= ndex to gro_process_tcp_item(). And same in gro_tcp6_reassemble(). >=20 > - /* > - * Check all packets in the flow and try to find a neighbor for > - * the input packet. > - */ > - cur_idx =3D tbl->flows[i].start_index; > - prev_idx =3D cur_idx; > - do { > - cmp =3D check_seq_option(&(tbl->items[cur_idx]), tcp_hdr, > - sent_seq, ip_id, pkt->l4_len, tcp_dl, 0, > - is_atomic); > - if (cmp) { > - if (merge_two_tcp4_packets(&(tbl->items[cur_idx]), > - pkt, cmp, sent_seq, ip_id, 0)) > - return 1; > - /* > - * Fail to merge the two packets, as the packet > - * length is greater than the max value. Store > - * the packet into the flow. > - */ > - if (insert_new_item(tbl, pkt, start_time, cur_idx, > - sent_seq, ip_id, is_atomic) =3D=3D > - INVALID_ARRAY_INDEX) > - return -1; > - return 0; > - } > - prev_idx =3D cur_idx; > - cur_idx =3D tbl->items[cur_idx].next_pkt_idx; > - } while (cur_idx !=3D INVALID_ARRAY_INDEX); > + return gro_process_tcp_item(pkt, tcp_hdr, tcp_dl, tbl->items, > item_idx, > + &tbl->item_num, tbl- > >max_item_num, > + ip_id, is_atomic, start_time); > +} >=20 > - /* Fail to find a neighbor, so store the packet into the flow. */ > - if (insert_new_item(tbl, pkt, start_time, prev_idx, sent_seq, > - ip_id, is_atomic) =3D=3D INVALID_ARRAY_INDEX) > - return -1;