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 89F0AA034C; Fri, 25 Feb 2022 15:34:04 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id E9C174115C; Fri, 25 Feb 2022 15:34:03 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by mails.dpdk.org (Postfix) with ESMTP id 3337E4068B for ; Fri, 25 Feb 2022 15:34:02 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1645799642; x=1677335642; h=from:to:subject:date:message-id:references:in-reply-to: content-transfer-encoding:mime-version; bh=FsQGUHhWaaZXUaKCGhJyd3pHi7uuTtfTM6utq3eSYf4=; b=Wb5KK8W6+u6G1bY9zVKTv2KIb27DX8k1G0ltS2Pn1vDj0S1sUGbDEjRt 2QFtU16NUKrx9B8QOF76msxuVD6VFy5lbtEgqyljYuHESIpnLkfi1mRDp hdetJKsFg3lfdm2cZYe+xfe9macOTmelY7iZBV+V1H+bKHadZmQe+el8f Av83d10WYO6YiqnjxMCWEdzYvfHh5Zp7A1bxjnkeHMd5r19lg15GKNW8o h2mhWshUc3U4Eo7nuYPce6g8S2C+ZEce5ntBCwIIcTZvpdJP5ZCQ43+qb T4N9yaNPX6kUmvhSE2vL6/tmXfXO2CqdtOcvCOa1UcBXAHGunEZhS8cRK w==; X-IronPort-AV: E=McAfee;i="6200,9189,10268"; a="250084668" X-IronPort-AV: E=Sophos;i="5.90,136,1643702400"; d="scan'208";a="250084668" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Feb 2022 06:34:01 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,136,1643702400"; d="scan'208";a="592498423" Received: from fmsmsx602.amr.corp.intel.com ([10.18.126.82]) by fmsmga008.fm.intel.com with ESMTP; 25 Feb 2022 06:34:01 -0800 Received: from fmsmsx607.amr.corp.intel.com (10.18.126.87) by fmsmsx602.amr.corp.intel.com (10.18.126.82) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.21; Fri, 25 Feb 2022 06:34:00 -0800 Received: from fmsmsx604.amr.corp.intel.com (10.18.126.84) by fmsmsx607.amr.corp.intel.com (10.18.126.87) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.21; Fri, 25 Feb 2022 06:34:00 -0800 Received: from fmsedg602.ED.cps.intel.com (10.1.192.136) by fmsmsx604.amr.corp.intel.com (10.18.126.84) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.21 via Frontend Transport; Fri, 25 Feb 2022 06:34:00 -0800 Received: from NAM04-BN8-obe.outbound.protection.outlook.com (104.47.74.48) by edgegateway.intel.com (192.55.55.71) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2308.20; Fri, 25 Feb 2022 06:33:59 -0800 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=kc8GvOAsHd/veb1PzUXHwD3Qli/FcTcZ1SIieTtF3pYe/WfcFSe68lFMohKKeLQvnoEDxuWg3O4uqncdoqc/a0H4P28q93XfYoCTRxLPPco8jnVQyGwzc+/rblBDHRa7/0PAVQctSfbYSEwyVLGY+07FGMBhutIc6++hExGR15xC11cmykzLdUO0PyGuQ3670oKm1GmMlzr/9af3ivYhG8Jm8cC3vSOkJLiY0N5FnXVkabaFqlc+pkAw7O1uX+AaaGs4pvOyqLTV82qRlbephJ+z7mVKSIfwStmSF74tPfMposZbszO/+9TGGd6g4Znee/AO54tChIc2OmNPhjFjlA== 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=ovZmpRe3zNkJyepMTBvu7UmWNxf+hV/+Tzf2H6Z+11o=; b=SLXj2BwgE8WbXLEaB4qQm/7qoWJelIHzqjKu2cnpPF06v1wauIwWbqoh+Wp4tnb6eBBIUzaEHqvuySq2agqNhqSLSwU25YhLs5Vk59yAKY54RgCC85F2i8WEFPPqDyipCQGfawdZpymjKsUVymON113f4PMexKWJVhpJwh9KXTAK8yx1a13Q4d8WODMe3JP7kLyWtV7jbfuTY2Ke22sjLMdldOQmrbnGhh/ajE8hbQi8twRfo0GC4ylj9SsCru0cF+fl1bIuDOYb5rSgG2oXca23mqqofxe8fO6WG8FXR+HhqHxJTwqqmRDHWOJR1WZwOaxbViUAbkHBFeCDC1CwrA== 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 DM6PR11MB4491.namprd11.prod.outlook.com (2603:10b6:5:204::19) by MN2PR11MB4510.namprd11.prod.outlook.com (2603:10b6:208:17b::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5017.22; Fri, 25 Feb 2022 14:33:57 +0000 Received: from DM6PR11MB4491.namprd11.prod.outlook.com ([fe80::8ccc:ed65:78fa:1b07]) by DM6PR11MB4491.namprd11.prod.outlook.com ([fe80::8ccc:ed65:78fa:1b07%4]) with mapi id 15.20.5017.025; Fri, 25 Feb 2022 14:33:57 +0000 From: "Ananyev, Konstantin" To: Huichao Cai , "dev@dpdk.org" Subject: RE: [PATCH v3] ip_frag: add IPv4 options fragment and test data Thread-Topic: [PATCH v3] ip_frag: add IPv4 options fragment and test data Thread-Index: AQHYJtGjWlsEzLPxpkKc2UccR/zoyqykVCYg Date: Fri, 25 Feb 2022 14:33:57 +0000 Message-ID: References: <1644915055-38172-1-git-send-email-chcchc88@163.com> <1645413440-3431-1-git-send-email-chcchc88@163.com> In-Reply-To: <1645413440-3431-1-git-send-email-chcchc88@163.com> Accept-Language: en-GB, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-product: dlpe-windows dlp-reaction: no-action dlp-version: 11.6.401.20 authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=intel.com; x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 2e49cf31-a103-4f1a-770d-08d9f86bdb3e x-ms-traffictypediagnostic: MN2PR11MB4510:EE_ x-microsoft-antispam-prvs: x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: t/ACJRFxUxxlv5Vb2yzbR/3/Z8FC6gsu2tVB1Fp1SDARJNNOIcS98dbrG1wDnfApYTBOtFv9HmMkLF/dOhnmkptrI/AD3lB+FWxR2xtRqX+RJqh6unozKJSq16RTN4++hcyAubWqPHVLOkE/x3aWiuUcFKE5n13to8gVsRylbgj1FIGFnr2csJquy5nBCwM3VqSfUoGv93AhvLT8ZGCya5tUX0ipRg2CA64oyTKBb1ahf0qwngsZAE+GWncdt0xJCrvsma+ZzhgOnusWEKEJ7SMR4iv0ymcrZKIfYuZy60EwpDv1/YBBphtR9xVtPQFwenJ9l92EesIabCnwGkxAlAgFfXnuNAmLHsaDhOIZ4aXNwCBgPUSeHsfgPNUjOPDr051ZG9w0PNpu0/tz6bjgMuBcX0yLLLtq2/OhXeVxHXYkCCAZf6A7X+JI8etJcoRI0s4ZY+Ck8xjMlj5BxyqrWDGl/l0LN1zezoEHfOht5OTrI1fZHFS+3/qwmp2/f4+I7DdbuHlboPRd3vZIdubriFYDqtTYYOyCcd6Gm8YY+1tYV/va5zUPx1Q9dl5lS54QkXH8vUfZ9Kjlr/BfGrBZjb9R1bX/CYawXKJyT/NisKDHWkbc4lGbKiTa2//I0rqx81ID37/FHDi/bwB3a5a6XT8cxg5lyxlFadgbTlSd9UchKfokQVaUNHTQuoHhgkNBCTxDrOPOp6IZn1sYKUenbA== x-forefront-antispam-report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:DM6PR11MB4491.namprd11.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230001)(366004)(30864003)(110136005)(508600001)(71200400001)(86362001)(186003)(9686003)(6506007)(83380400001)(26005)(316002)(5660300002)(2906002)(66556008)(66446008)(66946007)(66476007)(64756008)(33656002)(55016003)(82960400001)(38070700005)(52536014)(7696005)(38100700002)(76116006)(8676002)(8936002)(122000001)(579004); DIR:OUT; SFP:1102; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?AHGqGM9ZnJ8xelgmfWULNGCW3Agm1MiUIOlAUdHp9IJptFS9D3qM9f64Ti66?= =?us-ascii?Q?PLsHzKST+VXfaUZupfHBrt53lQyAcAtfnzJdZDXKzt8m0Fqos6RvTzXdzCY7?= =?us-ascii?Q?vcZb4vUw9pR1bDdpc4jslHFL9VZgZWb0qgmh3s5FB3E/aRQWcUwEN4PeXRMT?= =?us-ascii?Q?j8DcsFlDmze5n/15I74qGk4asb5TQ5KfavuqyPbKXpgqq+N/8JYc6eAMGEAW?= =?us-ascii?Q?X+ly0C4IY833TbKlAreNLZwiquJDI6YFTzu4hXot22THQ0GzUwhn3fASOv2l?= =?us-ascii?Q?kwexNHcPoHZjBJOBMHiMWtFxeWe2ErT1EmCcTdzF1B6ewNzY7pcvvWdfwZr+?= =?us-ascii?Q?7/s8Dx2mYaWWrMN/ahoFjY7l5tJdcutl/QKZD/Lbo50D+u0edss2owkzvZjj?= =?us-ascii?Q?sbFH/V27mCARYPSI5YTY5Oh1ncNYuV2ftLbaBgwH9qAZ+u8CuyPxTxv3/4GM?= =?us-ascii?Q?DVnFaH1JSpx1xB+kM1+xQHwi8XpBq4wapz2bmedrlGNtS9VpLxpYHAXRWsAK?= =?us-ascii?Q?Y87kL706zjm3xhP55eH+ckX0ipjdZXkuYgrDc5Y3kbKtPhr5485zLz+P9hrb?= =?us-ascii?Q?xrmKIiawVz8O39WuAgSJmPNnTQCeuBfdIms/J1s2y/7Hu2oWV5OoDOvrBoQb?= =?us-ascii?Q?tEmb6OLvWkGnhE+zYfhZWD1H0ZTOyAHRnG5wF/mfbenAgEDBxy8UUMb6JtPY?= =?us-ascii?Q?un/z0UFXZZlv3aiRR8zGNvVvBg9HmsyNDg2ke/N1qsY7GgTfV3ep2S5KvZdT?= =?us-ascii?Q?JwZRw1eCXmKo0R7uL8E4WScwRND0EHdoDmQJGjdbpqexrBqeZM1gDsXvNjL0?= =?us-ascii?Q?HoIrLiJXS+9DkiGKBHqWKVRA7OdU/TtpcKhvHB8Z0XPnZtMS+YopXGjHoOhr?= =?us-ascii?Q?9K6x0qekrUUccaden7y7wKrRjmKR8j2+BzTxhRfYtYaVJiM0WmKd7d4+pnDq?= =?us-ascii?Q?0WkVPUKOzuw3pwV89AnOY258rkBFBU15wGUz88m1OILDyawjqlTzOLI2a/32?= =?us-ascii?Q?I8Gx31JWeLAL7bZDsDF6akpNLijH6wmuOKZYG9pH1l981vOaWDx+UikwIp48?= =?us-ascii?Q?Z5EmefpjPnWguBeighsjYA/acClZJ5e00iafIh5/jp1mnVhQiVtfQNKQx7Zq?= =?us-ascii?Q?5mUG60X8avLNlEBs4pk1Q7sN0S2ZitUBrmJmT3hj1WlBKLHkSAzmcAwLI+mc?= =?us-ascii?Q?HSsaMZdxtglHm4umJCeFKlpn2JgRQ4t+GHrLYh0aCFrsvlmz8Xcy/HDuJVUu?= =?us-ascii?Q?oXVVN31sI8i/CoiXKCUaEWdUKaH8A/KmpOqKGgeDqlJyW0wN0WYZTzxInRWD?= =?us-ascii?Q?HPQFpGKixBZGkVVkYiy5eAgaNE9zHlfYS+OfRvN2Gh2XPbcQNIjUh0Tm8jHu?= =?us-ascii?Q?VA/2iq0Ab8XK6izYODybQWz0XkzDjRr0GTSHFlrXW4M3P2LDdUct0vCBDSVe?= =?us-ascii?Q?KBt1JWflYc2/mCUQaOA5TXcPhTPNWSro/3hERsgu2TJe3zADG73sVYz4iVfx?= =?us-ascii?Q?nOQf8A5CgN64nX0GJJCIUP9BX3oRQ//+YBo3cYOng8FAE7nug0BpflTMFlzM?= =?us-ascii?Q?GnaLiwfNJ7CEJv8k8HtgUdGXhN8NbStHrYYdmakN+2n64qq38gLEl95EJp19?= =?us-ascii?Q?WoAn35L7VCI1sb51R12V01BBPJg9b2HFhswDIrO5DypeDRRL1Zsr0ONqFHct?= =?us-ascii?Q?fWdf1Q=3D=3D?= 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: DM6PR11MB4491.namprd11.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 2e49cf31-a103-4f1a-770d-08d9f86bdb3e X-MS-Exchange-CrossTenant-originalarrivaltime: 25 Feb 2022 14:33:57.2504 (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: 1gHtJW+NU+yxQ0FC/O1j289pn+EYfCTAWqI20Cpc1DHotEDj/qGhEA6Wm76NGGX4349DYjftplMbhXecSh6NjQ5QEEZMkgwbQnAynBhyQEA= X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR11MB4510 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 Ho Huichao, > According to RFC791,the options may appear or not in datagrams. > They must be implemented by all IP modules (host and gateways). > What is optional is their transmission in any particular datagram, > not their implementation.So we have to deal with it during the > fragmenting process.Add some test data for the IPv4 header optional > field fragmenting. Apologies for delay in getting back to you. LGTM in general, just few extra questions/nits/suggestions below. >=20 > Signed-off-by: Huichao Cai > --- > app/test/test_ipfrag.c | 263 +++++++++++++++++++++++++++++= +++--- > lib/ip_frag/rte_ipv4_fragmentation.c | 77 +++++++++- > 2 files changed, 318 insertions(+), 22 deletions(-) >=20 > diff --git a/app/test/test_ipfrag.c b/app/test/test_ipfrag.c > index 1ced25a..996130d 100644 > --- a/app/test/test_ipfrag.c > +++ b/app/test/test_ipfrag.c > @@ -18,10 +18,96 @@ > #define NUM_MBUFS 128 > #define BURST 32 >=20 > +/* IP options */ > +#define RTE_IPOPT_EOL 0 > +#define RTE_IPOPT_NOP 1 > +#define RTE_IPOPT_COPIED(v) ((v) & 0x80) > +#define RTE_IPOPT_MAX_LEN 40 These macros are dups for what we have in rte_ipv4_fragmentation.c Would probably make sense to name them RTE_IPV4_IPOPT_... and put them=20 in some public .h to avoid duplication. > +#define RTE_IPOPT_MANUAL Could you clarify what this macro does? BTW, I assume it is a local one? If so, no need for RTE_ prefix. > +#ifdef RTE_IPOPT_MANUAL > +uint8_t expected_first_frag_ipv4_opts[] =3D { > + 0x07, 0x0b, 0x04, 0x00, > + 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x83, > + 0x07, 0x04, 0xc0, 0xa8, > + 0xe3, 0x96, 0x00, 0x00, > +}; > + > +uint8_t expected_sub_frag_ipv4_opts[] =3D { > + 0x83, 0x07, 0x04, 0xc0, > + 0xa8, 0xe3, 0x96, 0x00, > +}; > +#else > +/** > + * IPv4 Options > + */ > +struct test_ipv4_opt { > + __extension__ > + union { > + uint8_t type; /**< option type */ > + struct { > +#if RTE_BYTE_ORDER =3D=3D RTE_LITTLE_ENDIAN > + uint8_t number:5; /**< option number */ > + uint8_t category:2; /**< option class */ > + uint8_t copied:1; /**< option copy flag */ > +#elif RTE_BYTE_ORDER =3D=3D RTE_BIG_ENDIAN > + uint8_t copied:1; /**< option copy flag */ > + uint8_t category:2; /**< option class */ > + uint8_t number:5; /**< option number */ > +#endif > + } s_type; > + }; > + uint8_t length; /**< option length */ > + uint8_t pointer; /**< option pointer */ > + uint8_t data[37]; /**< option data */ > +} __rte_packed; > + > +struct test_ipv4_opt test_ipv4_opts[] =3D { > + { > + .s_type.copied =3D 0, > + .s_type.category =3D 0, > + .s_type.number =3D 7, > + .length =3D 11, > + .pointer =3D 4, > + }, > + { > + .s_type.copied =3D 1, > + .s_type.category =3D 0, > + .s_type.number =3D 3, > + .length =3D 7, > + .pointer =3D 4, > + .data[0] =3D 0xc0, > + .data[1] =3D 0xa8, > + .data[2] =3D 0xe3, > + .data[3] =3D 0x96, > + }, > +}; > +#endif > + > +struct test_opt_data { > + bool is_first_frag; /**< offset is 0 */ > + uint16_t len; /**< option data len */ > + uint8_t data[RTE_IPOPT_MAX_LEN]; /**< option data */ > +}; > + > static struct rte_mempool *pkt_pool, > *direct_pool, > *indirect_pool; >=20 > +static inline void > +hex_to_str(uint8_t *hex, uint16_t len, char *str) > +{ > + int i; > + > + for (i =3D 0; i < len; i++) { > + sprintf(str, "%02x", hex[i]); > + str +=3D 2; > + } > + *str =3D 0; > +} > + > static int > setup_buf_pool(void) > { > @@ -88,23 +174,78 @@ static void ut_teardown(void) > { > } >=20 > +static inline void > +test_get_ipv4_opt(bool is_first_frag, > + struct test_opt_data *expected_opt) > +{ > +#ifdef RTE_IPOPT_MANUAL > + if (is_first_frag) { > + expected_opt->len =3D sizeof(expected_first_frag_ipv4_opts); > + rte_memcpy(expected_opt->data, expected_first_frag_ipv4_opts, > + sizeof(expected_first_frag_ipv4_opts)); > + } else { > + expected_opt->len =3D sizeof(expected_sub_frag_ipv4_opts); > + rte_memcpy(expected_opt->data, expected_sub_frag_ipv4_opts, > + sizeof(expected_sub_frag_ipv4_opts)); > + } > +#else > + uint16_t i; > + uint16_t pos =3D 0; > + expected_opt->len =3D 0; > + > + for (i =3D 0; i < RTE_DIM(test_ipv4_opts); i++) { > + if (unlikely(pos + test_ipv4_opts[i].length > > + RTE_IPOPT_MAX_LEN)) > + return; > + > + if (is_first_frag) { > + rte_memcpy(expected_opt->data + pos, &test_ipv4_opts[i], > + test_ipv4_opts[i].length); > + expected_opt->len +=3D test_ipv4_opts[i].length; > + pos +=3D test_ipv4_opts[i].length; > + } else { > + if (test_ipv4_opts[i].s_type.copied) { > + rte_memcpy(expected_opt->data + pos, > + &test_ipv4_opts[i], > + test_ipv4_opts[i].length); > + expected_opt->len +=3D test_ipv4_opts[i].length; > + pos +=3D test_ipv4_opts[i].length; > + } > + } > + } > + > + expected_opt->len =3D RTE_ALIGN_CEIL(expected_opt->len, 4); > + memset(expected_opt->data + pos, RTE_IPOPT_EOL, > + expected_opt->len - pos); > +#endif > +} > + > static void > -v4_allocate_packet_of(struct rte_mbuf *b, int fill, > - size_t s, int df, uint8_t mf, uint16_t off, > - uint8_t ttl, uint8_t proto, uint16_t pktid) > +v4_allocate_packet_of(struct rte_mbuf *b, int fill, size_t s, > + int df, uint8_t mf, uint16_t off, uint8_t ttl, uint8_t proto, > + uint16_t pktid, bool have_opt, bool is_first_frag) > { > /* Create a packet, 2k bytes long */ > b->data_off =3D 0; > char *data =3D rte_pktmbuf_mtod(b, char *); > - rte_be16_t fragment_offset =3D 0; /**< fragmentation offset */ > + rte_be16_t fragment_offset =3D 0; /* fragmentation offset */ > + uint16_t iph_len; > + struct test_opt_data opt; >=20 > - memset(data, fill, sizeof(struct rte_ipv4_hdr) + s); > + opt.len =3D 0; > + > + if (have_opt) > + test_get_ipv4_opt(is_first_frag, &opt); > + > + iph_len =3D sizeof(struct rte_ipv4_hdr) + opt.len; > + memset(data, fill, iph_len + s); >=20 > struct rte_ipv4_hdr *hdr =3D (struct rte_ipv4_hdr *)data; >=20 > - hdr->version_ihl =3D 0x45; /* standard IP header... */ > + hdr->version_ihl =3D 0x40; /* ipv4 */ > + hdr->version_ihl +=3D (iph_len / 4); > hdr->type_of_service =3D 0; > - b->pkt_len =3D s + sizeof(struct rte_ipv4_hdr); > + b->pkt_len =3D s + iph_len; > b->data_len =3D b->pkt_len; > hdr->total_length =3D rte_cpu_to_be_16(b->pkt_len); > hdr->packet_id =3D rte_cpu_to_be_16(pktid); > @@ -131,6 +272,8 @@ static void ut_teardown(void) > hdr->hdr_checksum =3D 0; > hdr->src_addr =3D rte_cpu_to_be_32(0x8080808); > hdr->dst_addr =3D rte_cpu_to_be_32(0x8080404); > + > + rte_memcpy(hdr + 1, opt.data, opt.len); > } >=20 > static void > @@ -187,6 +330,43 @@ static void ut_teardown(void) > } > } >=20 > +static inline void > +test_get_frag_opt(struct rte_mbuf **mb, int32_t num, > + struct test_opt_data *opt, int ipv) > +{ > + int32_t i; > + > + for (i =3D 0; i < num; i++) { > + if (ipv =3D=3D 4) { > + struct rte_ipv4_hdr *iph =3D > + rte_pktmbuf_mtod(mb[i], struct rte_ipv4_hdr *); > + uint16_t header_len =3D (iph->version_ihl & > + RTE_IPV4_HDR_IHL_MASK) * > + RTE_IPV4_IHL_MULTIPLIER; > + uint16_t opt_len =3D header_len - > + sizeof(struct rte_ipv4_hdr); > + > + if ((rte_be_to_cpu_16(iph->fragment_offset) & > + RTE_IPV4_HDR_OFFSET_MASK) =3D=3D 0) > + opt->is_first_frag =3D true; > + else > + opt->is_first_frag =3D false; > + > + if (opt_len && (opt_len <=3D RTE_IPOPT_MAX_LEN)) { > + char *iph_opt =3D rte_pktmbuf_mtod_offset(mb[i], > + char *, sizeof(struct rte_ipv4_hdr)); > + opt->len =3D opt_len; > + rte_memcpy(opt->data, iph_opt, opt_len); > + } else { > + opt->len =3D RTE_IPOPT_MAX_LEN; > + memset(opt->data, RTE_IPOPT_EOL, > + sizeof(opt->data)); > + } > + opt++; > + } > + } > +} > + > static int > test_ip_frag(void) > { > @@ -206,32 +386,42 @@ static void ut_teardown(void) > uint16_t pkt_id; > int expected_frags; > uint16_t expected_fragment_offset[BURST]; > + bool have_opt; > + bool is_first_frag; > } tests[] =3D { > {4, 1280, 1400, 0, 0, 0, 64, IPPROTO_ICMP, RND_ID, 2, > - {0x2000, 0x009D}}, > + {0x2000, 0x009D}, 0}, > {4, 1280, 1400, 0, 0, 0, 64, IPPROTO_ICMP, 0, 2, > - {0x2000, 0x009D}}, > + {0x2000, 0x009D}, 0}, > {4, 600, 1400, 0, 0, 0, 64, IPPROTO_ICMP, RND_ID, 3, > - {0x2000, 0x2048, 0x0090}}, > + {0x2000, 0x2048, 0x0090}, 0}, > {4, 4, 1400, 0, 0, 0, 64, IPPROTO_ICMP, RND_ID, -EINVAL}, > {4, 600, 1400, 1, 0, 0, 64, IPPROTO_ICMP, RND_ID, -ENOTSUP}, > {4, 600, 1400, 0, 0, 0, 0, IPPROTO_ICMP, RND_ID, 3, > - {0x2000, 0x2048, 0x0090}}, > + {0x2000, 0x2046, 0x008C}, 1, 1}, > + /* The first fragment */ > + {4, 68, 104, 0, 1, 0, 0, IPPROTO_ICMP, RND_ID, 5, > + {0x2000, 0x2003, 0x2006, 0x2009, 0x200C}, 1, 1}, > + /* The middle fragment */ > {4, 68, 104, 0, 1, 13, 0, IPPROTO_ICMP, RND_ID, 3, > - {0x200D, 0x2013, 0x2019}}, > - > + {0x200D, 0x2012, 0x2017}, 1, 0}, > + /* The last fragment */ > + {4, 68, 104, 0, 0, 26, 0, IPPROTO_ICMP, RND_ID, 3, > + {0x201A, 0x201F, 0x0024}, 1, 0}, > {6, 1280, 1400, 0, 0, 0, 64, IPPROTO_ICMP, RND_ID, 2, > - {0x0001, 0x04D0}}, > + {0x0001, 0x04D0}, 0}, > {6, 1300, 1400, 0, 0, 0, 64, IPPROTO_ICMP, RND_ID, 2, > - {0x0001, 0x04E0}}, > + {0x0001, 0x04E0}, 0}, > {6, 4, 1400, 0, 0, 0, 64, IPPROTO_ICMP, RND_ID, -EINVAL}, > {6, 1300, 1400, 0, 0, 0, 0, IPPROTO_ICMP, RND_ID, 2, > - {0x0001, 0x04E0}}, > + {0x0001, 0x04E0}, 0}, > }; >=20 > for (i =3D 0; i < RTE_DIM(tests); i++) { > int32_t len =3D 0; > uint16_t fragment_offset[BURST]; > + struct test_opt_data opt_res[BURST]; > + struct test_opt_data opt_exp; > uint16_t pktid =3D tests[i].pkt_id; > struct rte_mbuf *pkts_out[BURST]; > struct rte_mbuf *b =3D rte_pktmbuf_alloc(pkt_pool); > @@ -250,7 +440,9 @@ static void ut_teardown(void) > tests[i].set_of, > tests[i].ttl, > tests[i].proto, > - pktid); > + pktid, > + tests[i].have_opt, > + tests[i].is_first_frag); > } else if (tests[i].ipv =3D=3D 6) { > v6_allocate_packet_of(b, 0x41414141, > tests[i].pkt_size, > @@ -275,17 +467,21 @@ static void ut_teardown(void) > if (len > 0) { > test_get_offset(pkts_out, len, > fragment_offset, tests[i].ipv); > + if (tests[i].have_opt) > + test_get_frag_opt(pkts_out, len, > + opt_res, > + tests[i].ipv); > test_free_fragments(pkts_out, len); > } >=20 > - printf("%zd: checking %d with %d\n", i, len, > + printf("[check frag number]%zd: checking %d with %d\n", i, len, > tests[i].expected_frags); > RTE_TEST_ASSERT_EQUAL(len, tests[i].expected_frags, > "Failed case %zd.\n", i); >=20 > if (len > 0) { > for (j =3D 0; j < (size_t)len; j++) { > - printf("%zd-%zd: checking %d with %d\n", > + printf("[check offset]%zd-%zd: checking %d with %d\n", > i, j, fragment_offset[j], > rte_cpu_to_be_16( > tests[i].expected_fragment_offset[j])); > @@ -294,6 +490,35 @@ static void ut_teardown(void) > tests[i].expected_fragment_offset[j]), > "Failed case %zd.\n", i); > } > + > + if (tests[i].have_opt && (tests[i].ipv =3D=3D 4)) { > + for (j =3D 0; j < (size_t)len; j++) { > + char opt_res_str[2 * > + RTE_IPOPT_MAX_LEN + 1]; > + char opt_exp_str[2 * > + RTE_IPOPT_MAX_LEN + 1]; > + > + test_get_ipv4_opt( > + opt_res[j].is_first_frag, > + &opt_exp); > + hex_to_str(opt_res[j].data, > + opt_res[j].len, > + opt_res_str); > + hex_to_str(opt_exp.data, > + opt_exp.len, > + opt_exp_str); > + > + printf( > + "[check ipv4 option]%zd-%zd: checking (%u)%s with (%u)%s\n", > + i, j, > + opt_res[j].len, opt_res_str, > + opt_exp.len, opt_exp_str); > + RTE_TEST_ASSERT_SUCCESS( > + strcmp(opt_res_str, > + opt_exp_str), > + "Failed case %zd.\n", i); > + } > + } > } >=20 > } > diff --git a/lib/ip_frag/rte_ipv4_fragmentation.c b/lib/ip_frag/rte_ipv4_= fragmentation.c > index 2e7739d..57b8bc1 100644 > --- a/lib/ip_frag/rte_ipv4_fragmentation.c > +++ b/lib/ip_frag/rte_ipv4_fragmentation.c > @@ -12,6 +12,12 @@ >=20 > #include "ip_frag_common.h" >=20 > +/* IP options */ > +#define RTE_IPOPT_EOL 0 > +#define RTE_IPOPT_NOP 1 > +#define RTE_IPOPT_COPIED(v) ((v) & 0x80) > +#define RTE_IPOPT_MAX_LEN 40 > + > /* Fragment Offset */ > #define RTE_IPV4_HDR_DF_SHIFT 14 > #define RTE_IPV4_HDR_MF_SHIFT 13 > @@ -22,6 +28,8 @@ >=20 > #define IPV4_HDR_FO_ALIGN (1 << RTE_IPV4_HDR_FO_SHIFT) >=20 > +#define RTE_IPV4_HDR_MAX_LEN 60 > + > static inline void __fill_ipv4hdr_frag(struct rte_ipv4_hdr *dst, > const struct rte_ipv4_hdr *src, uint16_t header_len, > uint16_t len, uint16_t fofs, uint16_t dofs, uint32_t mf) > @@ -41,6 +49,50 @@ static inline void __free_fragments(struct rte_mbuf *m= b[], uint32_t num) > rte_pktmbuf_free(mb[i]); > } >=20 > +static inline void __create_ipopt_frag_hdr(uint8_t *iph, > + uint16_t *ipopt_len, uint8_t *ipopt_frag_hdr) > +{ Instead of returning void and having out parameter (ipopt_len), why just not make it a return value? static inline uint16_t __create_ipopt_frag_hdr(const uint8_t *iph, uint8_t * ipopt_frag_hdr, uint1= 6_t len) { .... return ipopt_len; } > + uint16_t len =3D *ipopt_len; > + struct rte_ipv4_hdr *iph_opt =3D (struct rte_ipv4_hdr *)ipopt_frag_hdr; > + > + *ipopt_len =3D 0; > + rte_memcpy(ipopt_frag_hdr, iph, sizeof(struct rte_ipv4_hdr)); > + iph_opt->ihl =3D sizeof(struct rte_ipv4_hdr) / RTE_IPV4_IHL_MULTIPLIER; We probably can update ihl once at the very end of this function. > + ipopt_frag_hdr +=3D sizeof(struct rte_ipv4_hdr); > + > + if (unlikely(len > RTE_IPOPT_MAX_LEN)) > + return; > + > + uint8_t *p_opt =3D iph + sizeof(struct rte_ipv4_hdr); > + > + while (len > 0) { > + if (unlikely(*p_opt =3D=3D RTE_IPOPT_NOP)) { > + len--; > + p_opt++; > + continue; > + } else if (unlikely(*p_opt =3D=3D RTE_IPOPT_EOL)) > + break; > + > + if (unlikely(p_opt[1] < 2 || p_opt[1] > len)) > + break; > + > + if (RTE_IPOPT_COPIED(*p_opt)) { > + rte_memcpy(ipopt_frag_hdr + *ipopt_len, > + p_opt, p_opt[1]); > + *ipopt_len +=3D p_opt[1]; > + } > + > + len -=3D p_opt[1]; > + p_opt +=3D p_opt[1]; > + } > + > + len =3D RTE_ALIGN_CEIL(*ipopt_len, RTE_IPV4_IHL_MULTIPLIER); > + memset(ipopt_frag_hdr + *ipopt_len, > + RTE_IPOPT_EOL, len - *ipopt_len); > + *ipopt_len =3D len; > + iph_opt->ihl +=3D len / RTE_IPV4_IHL_MULTIPLIER; > +} > + > /** > * IPv4 fragmentation. > * > @@ -76,6 +128,8 @@ static inline void __free_fragments(struct rte_mbuf *m= b[], uint32_t num) > uint32_t more_in_segs; > uint16_t fragment_offset, flag_offset, frag_size, header_len; > uint16_t frag_bytes_remaining; > + uint8_t ipopt_frag_hdr[RTE_IPV4_HDR_MAX_LEN]; > + uint16_t ipopt_len; >=20 > /* > * Formal parameter checking. > @@ -117,6 +171,7 @@ static inline void __free_fragments(struct rte_mbuf *= mb[], uint32_t num) > in_seg_data_pos =3D header_len; > out_pkt_pos =3D 0; > fragment_offset =3D 0; > + ipopt_len =3D header_len - sizeof(struct rte_ipv4_hdr); >=20 > more_in_segs =3D 1; > while (likely(more_in_segs)) { > @@ -188,10 +243,26 @@ static inline void __free_fragments(struct rte_mbuf= *mb[], uint32_t num) > (uint16_t)out_pkt->pkt_len, > flag_offset, fragment_offset, more_in_segs); >=20 > - fragment_offset =3D (uint16_t)(fragment_offset + > - out_pkt->pkt_len - header_len); > + /* Create a separate IP header to handle frag options. */ > + if (unlikely((fragment_offset =3D=3D 0) && > + ((flag_offset & RTE_IPV4_HDR_OFFSET_MASK) =3D=3D 0) && > + (ipopt_len))) { > + __create_ipopt_frag_hdr((uint8_t *)in_hdr, > + &ipopt_len, ipopt_frag_hdr); Can we probably do that before the loop (as we have to do it only once anyw= ay? Something like: .... ipopt_len =3D header_len - sizeof(struct rte_ipv4_hdr); if (ipopt_len > RTE_IPOPT_MAX_LEN) return -EINVAL; if (ipopt_len !=3D 0) ipopt_len =3D __create_ipopt_frag_hdr((in_hdr, ipopt_frag_hdr, ipopt_len); .... And then: while (likely(more_in_segs)) { ... if (ipopt_len ! =3D 0) in_hdr =3D (struct rte_ipv4_hdr *)ipopt_frag_hdr;=09 } > + > + fragment_offset =3D (uint16_t)(fragment_offset + > + out_pkt->pkt_len - header_len); >=20 > - out_pkt->l3_len =3D header_len; > + out_pkt->l3_len =3D header_len; > + > + header_len =3D sizeof(struct rte_ipv4_hdr) + ipopt_len; > + in_hdr =3D (struct rte_ipv4_hdr *)ipopt_frag_hdr; > + } else { > + fragment_offset =3D (uint16_t)(fragment_offset + > + out_pkt->pkt_len - header_len); > + > + out_pkt->l3_len =3D header_len; > + } >=20 > /* Write the fragment to the output list */ > pkts_out[out_pkt_pos] =3D out_pkt; > -- > 1.8.3.1