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 629DB45B42; Tue, 15 Oct 2024 10:21:44 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 4FB4040616; Tue, 15 Oct 2024 10:21:44 +0200 (CEST) Received: from EUR05-DB8-obe.outbound.protection.outlook.com (mail-db8eur05on2069.outbound.protection.outlook.com [40.107.20.69]) by mails.dpdk.org (Postfix) with ESMTP id 8E64B40616 for ; Tue, 15 Oct 2024 10:21:42 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=VC2hHOipzgYJRA7YOEhoRBMRm3gqRb+pwGhK1uPFBYAWPv7UaAhzKQizPrnE7dsuSQGS0zNkj/MFH/HITwlunUWypcN84Pj0SIsLJWMO6znDuGKukTKCrBj2zn5bl+T5gMEoc28GOZVWCx9OfvX0BEmSLpUDSXHw34239gCWMn8KYuT6EY5k8I6Cx+kb6x8WmZLSeX9DmzC4Rn9i69i3Psd2HRrJ0dzYLQO94CEvQ0GMdWG0qp9/SItxIDaWPWs6jqcPuQa6slX3Mabc/IRCXRIzlAo6WW3qi183BhX/IzHo2lgXgZZBHoPlRcg9n7t5KueLeDmEHlx27h6UXbJV/A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=iqQND964BLwZUk1awRxJMnNZq05TTlFU9+nnYZlX+QU=; b=N69rPNxrq6AZsUImotz2e+P9ZKAdjVmEYMW4NKKhXsfYGPdRpBDB68ioa1eObB1x2QJ0lgbgY/Tjjs6BSWWwfdwTPG9gMem2N0gsXrl63HIp1Dxgshdq+2RMuwRmrLZMi8wMllKNn6bj/TCNtG05r6BVkq0WqCF5abxt3W2vFUaksH1cXdfjzmhdPvHNeFDg66VLx7ED/mCPzNLTAx8cMj9uaaq2EO0qKY0oNs4lmJhIclPiZnRT80rZvNF1W1Y/x2/ZMrc/Kz9OClG8/4k2ZxGk2MuEsDA7QArYQlZV7os5XNbPiapNRKkVBDcociqH3N33Ed64RDt++gATq30FlA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 192.176.1.74) smtp.rcpttodomain=dpdk.org smtp.mailfrom=ericsson.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=ericsson.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ericsson.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=iqQND964BLwZUk1awRxJMnNZq05TTlFU9+nnYZlX+QU=; b=EzxLUj45HsbkTLR3VfWA+Co3saU/K3H7tj4n7KXXCqfSV5F/z7veH9vSoWwBSuc/3EMtKy5r/qVFHa/5qpYo/bGlkAUaoZb18y1TV2FlWas7T6Gi18mEKrMl/fYjrDdMk8k5fAQ4jfFGlkdsBoApyDtkKFpOuvPLX6E4vg8o9yHWJT+q6vO7L/F4km0UHa2JwCTnAhMdPGtaLhCEdpDfPGcT8ZAhIC8D18ABwLN+hkEtoS04eMjP2oe9Z7HhX4+ermRitl7N0y2K747AdXIiza17h+2Pe/uCCNTnog/pclNBNB1WVPGlv4YRPd3+qbGr6q3aK1cPSijUs2p+MOepmw== Received: from DUZP191CA0024.EURP191.PROD.OUTLOOK.COM (2603:10a6:10:4f9::21) by DBAPR07MB6885.eurprd07.prod.outlook.com (2603:10a6:10:198::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8048.27; Tue, 15 Oct 2024 08:21:35 +0000 Received: from DU2PEPF00028CFF.eurprd03.prod.outlook.com (2603:10a6:10:4f9:cafe::f7) by DUZP191CA0024.outlook.office365.com (2603:10a6:10:4f9::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8069.17 via Frontend Transport; Tue, 15 Oct 2024 08:21:35 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 192.176.1.74) smtp.mailfrom=ericsson.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=ericsson.com; Received-SPF: Pass (protection.outlook.com: domain of ericsson.com designates 192.176.1.74 as permitted sender) receiver=protection.outlook.com; client-ip=192.176.1.74; helo=oa.msg.ericsson.com; pr=C Received: from oa.msg.ericsson.com (192.176.1.74) by DU2PEPF00028CFF.mail.protection.outlook.com (10.167.242.183) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8069.17 via Frontend Transport; Tue, 15 Oct 2024 08:21:35 +0000 Received: from seroius18814.sero.gic.ericsson.se (153.88.142.248) by smtp-central.internal.ericsson.com (100.87.178.65) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Tue, 15 Oct 2024 10:21:35 +0200 Received: from seroiuts03116.sero.gic.ericsson.se (seroiuts03116.sero.gic.ericsson.se [10.210.134.60]) by seroius18814.sero.gic.ericsson.se (Postfix) with ESMTP id 0341A4020C05; Tue, 15 Oct 2024 10:21:34 +0200 (CEST) Received: by seroiuts03116.sero.gic.ericsson.se (Postfix, from userid 7401342) id E6C0B60424AF; Tue, 15 Oct 2024 10:21:34 +0200 (CEST) From: To: CC: , Vignesh PS Subject: [PATCH v2] ip_frag: support IPv6 reassembly with extensions Date: Tue, 15 Oct 2024 10:21:33 +0200 Message-ID: <20241015082133.3910533-1-vignesh.purushotham.srinivas@ericsson.com> X-Mailer: git-send-email 2.37.3 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DU2PEPF00028CFF:EE_|DBAPR07MB6885:EE_ X-MS-Office365-Filtering-Correlation-Id: c0e1d508-fa55-4f69-dc75-08dcecf26283 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|82310400026|1800799024|376014|36860700013; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?FdkKYiWEe6mXKLMLz/4/BCYAk8dZzQaQYCV907KKXJJCBZBVrWEvpHVogzYN?= =?us-ascii?Q?hpthTAXI8Dcp33RZJImIW3yy+10FtVCJA9CTQTpiHiQEJ42HN+Hiq7xn1mSO?= =?us-ascii?Q?ls0o2LmbijRVju/hctxVy4SEoGu4vs0wKcow3nHRbK249/8pvLf8X6aFRGa8?= =?us-ascii?Q?zfn/0o2czy+lo1OZDoePeuEWxrH7YUykepDWPE923M5WPkrP0qYMn31YtDaH?= =?us-ascii?Q?0UJGdymV1PXnl2PWBYux8t5NnyNe6veFZsN3tZS+NjJdcDQs7goszEyu6bq3?= =?us-ascii?Q?faicVLFRcD5A0i7gpfKwQjFefAxTrNuHbZCU5nEJaX7b3mRlpxwfDCn9jICx?= =?us-ascii?Q?sRX2Z2kjEiJ7OYeVFF7xw9unG7sNyXcHHxBwEdBE8ioRL2StYn3AlZ/m6VBr?= =?us-ascii?Q?RYm4zaE8YwZEp34fCVz7AvJL/14sVBlCnPgyTtqbed8li/TOEZJYWlavK8cD?= =?us-ascii?Q?7YPqIrrNuIOXQPLbcHJdD441Zixq9dFwZ3HLc3KGRn4kKpFHBrBf78dEcDLi?= =?us-ascii?Q?MIo+Gbzn2J7pR/elvEoRyLsL/ttNJqhGxUVHM5d/h0H+lO3Ku5PLNGLtqEdW?= =?us-ascii?Q?UIJA0xkme52bHr6Ohym+URGmpZTCExnJPhpq2pB92843X9or318D4908YK35?= =?us-ascii?Q?J+31W5K/pMfqyUwTvkWuVRFTcPz15tME3Ez8mobAkRusxSWZebZoxb3ui1+/?= =?us-ascii?Q?pfNgjLWBXN3nsjvmM6Ff24KVEeM5aWDWrzonuy9KRskadfCxVk5k5jBCRGLO?= =?us-ascii?Q?LNW54ZdsgILQdY5Kt1SJ5iHvM3DbXc10qdXy8pig2NBKwda6w7ASdfgZTwzK?= =?us-ascii?Q?MtPVJyHIf2iVwURirODdRoh7OESyJ+gkn6t8PBF5oRMOOU68fj0UklDzWmbc?= =?us-ascii?Q?+3v1dd4TvdJjaRSKa5b/sWvnfryTzTY9tJtAVaUJBh+nuP57FQ60yuubPD3b?= =?us-ascii?Q?xsXra6+d2VexjZK0FtoA2k7I+c6DXShkJEKWZDhOsMokq3demQlxp72FqW0J?= =?us-ascii?Q?qrWNXkaFP5vUuMD6CuoQufO4yeegdLyeiTvoHznd//eMQKfd7PBBR7wDNXAy?= =?us-ascii?Q?7XhO02FMw552UPkrqi1OPTOARE6mWmgH7d1SfN1Cx1kkL7fgfc1HjVkgS4om?= =?us-ascii?Q?nlIz5fy4uTt+LOoKKZdsBOBf3bXYFabplfvAYpz0bo2KfgVYDGqBIoQCRY1h?= =?us-ascii?Q?mNv4Z3f+EM8WKI8XCaUGClCoHGcFqM+iV9S5pU93TaKBDG8nch0IJgJXUYep?= =?us-ascii?Q?6JTNO1BRWQL+NImL2R8h2K7HlW9SgNWGN7JV2ELEBC2TBuKPSG8UAixBC4yW?= =?us-ascii?Q?9GWFy/IyM6SCEUgBm2QaAyv9UCls0z2wTIvldyJWbKJ4nar1lEsjbS02HsLr?= =?us-ascii?Q?Nwi4M6o=3D?= X-Forefront-Antispam-Report: CIP:192.176.1.74; CTRY:SE; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:oa.msg.ericsson.com; PTR:office365.se.ericsson.net; CAT:NONE; SFS:(13230040)(82310400026)(1800799024)(376014)(36860700013); DIR:OUT; SFP:1101; X-OriginatorOrg: ericsson.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Oct 2024 08:21:35.8036 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: c0e1d508-fa55-4f69-dc75-08dcecf26283 X-MS-Exchange-CrossTenant-Id: 92e84ceb-fbfd-47ab-be52-080c6b87953f X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=92e84ceb-fbfd-47ab-be52-080c6b87953f; Ip=[192.176.1.74]; Helo=[oa.msg.ericsson.com] X-MS-Exchange-CrossTenant-AuthSource: DU2PEPF00028CFF.eurprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DBAPR07MB6885 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 From: Vignesh PS Add support to ip_frag library to perform IPv6 reassembly when extension headers are present before the fragment extension in the packet. Signed-off-by: Vignesh PS --- .mailmap | 1 + app/test/test_reassembly_perf.c | 163 +++++++++++++++++++----------- lib/ip_frag/ip_frag_common.h | 4 + lib/ip_frag/ip_reassembly.h | 2 + lib/ip_frag/rte_ipv6_reassembly.c | 75 ++++++++++++-- 5 files changed, 179 insertions(+), 66 deletions(-) diff --git a/.mailmap b/.mailmap index ed4ea17c4c..1bd3885424 100644 --- a/.mailmap +++ b/.mailmap @@ -1555,6 +1555,7 @@ Viacheslav Ovsiienko Victor Kaplansky Victor Raj Vidya Sagar Velumuri +Vignesh PS Vignesh Sridhar Vijayakumar Muthuvel Manickam Vijaya Mohan Guvva diff --git a/app/test/test_reassembly_perf.c b/app/test/test_reassembly_perf.c index 3912179022..6090182943 100644 --- a/app/test/test_reassembly_perf.c +++ b/app/test/test_reassembly_perf.c @@ -47,6 +47,16 @@ static struct rte_mbuf *mbufs[MAX_FLOWS][MAX_FRAGMENTS]; static uint8_t frag_per_flow[MAX_FLOWS]; static uint32_t flow_cnt; +struct ipv6_extension_routing { + uint8_t next_header; + uint8_t length; + uint8_t type; + uint8_t segments; + uint32_t data; +}; + +#define IPV6_ROUTING_HDR_SIZE sizeof(struct ipv6_extension_routing) + #define FILL_MODE_LINEAR 0 #define FILL_MODE_RANDOM 1 #define FILL_MODE_INTERLEAVED 2 @@ -108,15 +118,15 @@ static void reassembly_print_banner(const char *proto_str) { printf("+==============================================================" - "============================================+\n"); - printf("| %-32s| %-3s : %-58d|\n", proto_str, "Flow Count", MAX_FLOWS); + "===========================================================+\n"); + printf("| %-32s| %-3s : %-73d|\n", proto_str, "Flow Count", MAX_FLOWS); printf("+================+================+=============+=============+" - "========================+===================+\n"); - printf("%-17s%-17s%-14s%-14s%-25s%-20s\n", "| Fragment Order", - "| Fragments/Flow", "| Outstanding", "| Cycles/Flow", + "========================+==================================+\n"); + printf("%-17s%-17s%-15s%-14s%-14s%-25s%-20s\n", "| Fragment Order", + "| Fragments/Flow", "| Extensions", "| Outstanding", "| Cycles/Flow", "| Cycles/Fragment insert", "| Cycles/Reassembly |"); printf("+================+================+=============+=============+" - "========================+===================+\n"); + "========================+==================================+\n"); } static void @@ -272,9 +282,10 @@ ipv4_frag_pkt_setup(uint8_t fill_mode, uint8_t nb_frag) static void ipv6_frag_fill_data(struct rte_mbuf **mbuf, uint8_t nb_frags, uint32_t flow_id, - uint8_t fill_mode) + uint8_t fill_mode, uint8_t num_exts) { struct ipv6_extension_fragment *frag_hdr; + struct ipv6_extension_routing *routing_hdr; struct rte_ether_hdr *eth_hdr; struct rte_ipv6_hdr *ip_hdr; struct rte_udp_hdr *udp_hdr; @@ -303,15 +314,18 @@ ipv6_frag_fill_data(struct rte_mbuf **mbuf, uint8_t nb_frags, uint32_t flow_id, eth_hdr = rte_pktmbuf_mtod(frag, struct rte_ether_hdr *); ip_hdr = rte_pktmbuf_mtod_offset(frag, struct rte_ipv6_hdr *, sizeof(struct rte_ether_hdr)); + udp_hdr = rte_pktmbuf_mtod_offset( frag, struct rte_udp_hdr *, sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv6_hdr) + + num_exts * IPV6_ROUTING_HDR_SIZE + RTE_IPV6_FRAG_HDR_SIZE); frag_hdr = rte_pktmbuf_mtod_offset( frag, struct ipv6_extension_fragment *, sizeof(struct rte_ether_hdr) + - sizeof(struct rte_ipv6_hdr)); + sizeof(struct rte_ipv6_hdr) + + num_exts * IPV6_ROUTING_HDR_SIZE); rte_ether_unformat_addr("02:00:00:00:00:01", ð_hdr->dst_addr); @@ -334,11 +348,15 @@ ipv6_frag_fill_data(struct rte_mbuf **mbuf, uint8_t nb_frags, uint32_t flow_id, * Initialize IP header. */ pkt_len = (uint16_t)(pkt_len + sizeof(struct rte_ipv6_hdr) + - RTE_IPV6_FRAG_HDR_SIZE); + num_exts * IPV6_ROUTING_HDR_SIZE + + RTE_IPV6_FRAG_HDR_SIZE); ip_hdr->vtc_flow = rte_cpu_to_be_32(IP6_VERSION << 28); ip_hdr->payload_len = rte_cpu_to_be_16(pkt_len - sizeof(struct rte_ipv6_hdr)); - ip_hdr->proto = IPPROTO_FRAGMENT; + if (num_exts > 0) + ip_hdr->proto = IPPROTO_ROUTING; + else + ip_hdr->proto = IPPROTO_FRAGMENT; ip_hdr->hop_limits = IP_DEFTTL; memcpy(ip_hdr->src_addr, ip6_addr, sizeof(ip_hdr->src_addr)); memcpy(ip_hdr->dst_addr, ip6_addr, sizeof(ip_hdr->dst_addr)); @@ -352,6 +370,24 @@ ipv6_frag_fill_data(struct rte_mbuf **mbuf, uint8_t nb_frags, uint32_t flow_id, ip_hdr->dst_addr[8] = (flow_id >> 8) & 0xff; ip_hdr->dst_addr[9] = flow_id & 0xff; + for (uint8_t exts = 0; exts < num_exts; exts++) { + routing_hdr = rte_pktmbuf_mtod_offset( + frag, struct ipv6_extension_routing *, + sizeof(struct rte_ether_hdr) + + sizeof(struct rte_ipv6_hdr) + + exts * IPV6_ROUTING_HDR_SIZE); + + routing_hdr->length = 0; /* zero because extension is bare, no data */ + routing_hdr->type = 4; + routing_hdr->segments = num_exts - exts - 1; + routing_hdr->data = 0; + + if (exts == num_exts - 1) + routing_hdr->next_header = IPPROTO_FRAGMENT; + else + routing_hdr->next_header = IPPROTO_ROUTING; + } + frag_hdr->next_header = IPPROTO_UDP; frag_hdr->reserved = 0; frag_hdr->frag_data = rte_cpu_to_be_16(frag_offset); @@ -361,7 +397,9 @@ ipv6_frag_fill_data(struct rte_mbuf **mbuf, uint8_t nb_frags, uint32_t flow_id, frag->pkt_len = frag->data_len; frag->l2_len = sizeof(struct rte_ether_hdr); frag->l3_len = - sizeof(struct rte_ipv6_hdr) + RTE_IPV6_FRAG_HDR_SIZE; + sizeof(struct rte_ipv6_hdr) + + num_exts * IPV6_ROUTING_HDR_SIZE + + RTE_IPV6_FRAG_HDR_SIZE; } if (fill_mode == FILL_MODE_RANDOM) @@ -369,7 +407,7 @@ ipv6_frag_fill_data(struct rte_mbuf **mbuf, uint8_t nb_frags, uint32_t flow_id, } static int -ipv6_rand_frag_pkt_setup(uint8_t fill_mode, uint8_t max_frag) +ipv6_rand_frag_pkt_setup(uint8_t fill_mode, uint8_t max_frag, uint8_t num_exts) { uint8_t nb_frag; int i; @@ -379,7 +417,7 @@ ipv6_rand_frag_pkt_setup(uint8_t fill_mode, uint8_t max_frag) if (rte_mempool_get_bulk(pkt_pool, (void **)mbufs[i], nb_frag) < 0) return TEST_FAILED; - ipv6_frag_fill_data(mbufs[i], nb_frag, i, fill_mode); + ipv6_frag_fill_data(mbufs[i], nb_frag, i, fill_mode, num_exts); frag_per_flow[i] = nb_frag; } flow_cnt = i; @@ -388,7 +426,7 @@ ipv6_rand_frag_pkt_setup(uint8_t fill_mode, uint8_t max_frag) } static int -ipv6_frag_pkt_setup(uint8_t fill_mode, uint8_t nb_frag) +ipv6_frag_pkt_setup(uint8_t fill_mode, uint8_t nb_frag, uint8_t num_exts) { int i; @@ -396,7 +434,7 @@ ipv6_frag_pkt_setup(uint8_t fill_mode, uint8_t nb_frag) if (rte_mempool_get_bulk(pkt_pool, (void **)mbufs[i], nb_frag) < 0) return TEST_FAILED; - ipv6_frag_fill_data(mbufs[i], nb_frag, i, fill_mode); + ipv6_frag_fill_data(mbufs[i], nb_frag, i, fill_mode, num_exts); frag_per_flow[i] = nb_frag; } flow_cnt = i; @@ -414,7 +452,7 @@ frag_pkt_teardown(void) } static void -reassembly_print_stats(int8_t nb_frags, uint8_t fill_order, +reassembly_print_stats(int8_t nb_frags, uint8_t fill_order, uint8_t num_exts, uint32_t outstanding, uint64_t cyc_per_flow, uint64_t cyc_per_frag_insert, uint64_t cyc_per_reassembly) @@ -440,12 +478,12 @@ reassembly_print_stats(int8_t nb_frags, uint8_t fill_order, break; } - printf("| %-14s | %-14s | %-11d | %-11" PRIu64 " | %-22" PRIu64 + printf("| %-14s | %-14s | %-12d | %-11d | %-11" PRIu64 " | %-22" PRIu64 " | %-17" PRIu64 " |\n", - order_str, frag_str, outstanding, cyc_per_flow, + order_str, frag_str, num_exts, outstanding, cyc_per_flow, cyc_per_frag_insert, cyc_per_reassembly); printf("+================+================+=============+=============+" - "========================+===================+\n"); + "========================+==================================+\n"); } static void @@ -501,7 +539,7 @@ ipv4_reassembly_perf(int8_t nb_frags, uint8_t fill_order) mbufs[i][0] = buf_out; } - reassembly_print_stats(nb_frags, fill_order, 0, total_cyc / flow_cnt, + reassembly_print_stats(nb_frags, fill_order, 0, 0, total_cyc / flow_cnt, total_empty_cyc / frag_processed, total_reassembled_cyc / flow_cnt); @@ -576,7 +614,7 @@ ipv4_outstanding_reassembly_perf(int8_t nb_frags, uint8_t fill_order, mbufs[i][0] = buf_out; } - reassembly_print_stats(nb_frags, fill_order, outstanding, + reassembly_print_stats(nb_frags, fill_order, 0, outstanding, total_cyc / flow_cnt, total_empty_cyc / frag_processed, total_reassembled_cyc / flow_cnt); @@ -642,7 +680,7 @@ ipv4_reassembly_interleaved_flows_perf(uint8_t nb_frags) } } - reassembly_print_stats(nb_frags, FILL_MODE_INTERLEAVED, 0, + reassembly_print_stats(nb_frags, FILL_MODE_INTERLEAVED, 0, 0, total_cyc / flow_cnt, total_empty_cyc / frag_processed, total_reassembled_cyc / flow_cnt); @@ -651,7 +689,7 @@ ipv4_reassembly_interleaved_flows_perf(uint8_t nb_frags) } static int -ipv6_reassembly_perf(int8_t nb_frags, uint8_t fill_order) +ipv6_reassembly_perf(int8_t nb_frags, uint8_t fill_order, uint8_t num_exts) { struct rte_ip_frag_death_row death_row; uint64_t total_reassembled_cyc = 0; @@ -673,8 +711,8 @@ ipv6_reassembly_perf(int8_t nb_frags, uint8_t fill_order) struct ipv6_extension_fragment *frag_hdr = rte_pktmbuf_mtod_offset( buf, struct ipv6_extension_fragment *, - buf->l2_len + - sizeof(struct rte_ipv6_hdr)); + buf->l2_len + sizeof(struct rte_ipv6_hdr) + + num_exts * IPV6_ROUTING_HDR_SIZE); tstamp = rte_rdtsc_precise(); buf_out = rte_ipv6_frag_reassemble_packet( @@ -699,7 +737,7 @@ ipv6_reassembly_perf(int8_t nb_frags, uint8_t fill_order) mbufs[i][0] = buf_out; } - reassembly_print_stats(nb_frags, fill_order, 0, total_cyc / flow_cnt, + reassembly_print_stats(nb_frags, fill_order, num_exts, 0, total_cyc / flow_cnt, total_empty_cyc / frag_processed, total_reassembled_cyc / flow_cnt); @@ -708,7 +746,7 @@ ipv6_reassembly_perf(int8_t nb_frags, uint8_t fill_order) static int ipv6_outstanding_reassembly_perf(int8_t nb_frags, uint8_t fill_order, - uint32_t outstanding) + uint32_t outstanding, uint8_t num_exts) { struct rte_ip_frag_death_row death_row; uint64_t total_reassembled_cyc = 0; @@ -731,8 +769,8 @@ ipv6_outstanding_reassembly_perf(int8_t nb_frags, uint8_t fill_order, struct ipv6_extension_fragment *frag_hdr = rte_pktmbuf_mtod_offset( buf, struct ipv6_extension_fragment *, - buf->l2_len + - sizeof(struct rte_ipv6_hdr)); + buf->l2_len + sizeof(struct rte_ipv6_hdr) + + num_exts * IPV6_ROUTING_HDR_SIZE); tstamp = rte_rdtsc_precise(); buf_out = rte_ipv6_frag_reassemble_packet( @@ -761,8 +799,8 @@ ipv6_outstanding_reassembly_perf(int8_t nb_frags, uint8_t fill_order, struct ipv6_extension_fragment *frag_hdr = rte_pktmbuf_mtod_offset( buf, struct ipv6_extension_fragment *, - buf->l2_len + - sizeof(struct rte_ipv6_hdr)); + buf->l2_len + sizeof(struct rte_ipv6_hdr) + + num_exts * IPV6_ROUTING_HDR_SIZE); tstamp = rte_rdtsc_precise(); buf_out = rte_ipv6_frag_reassemble_packet( @@ -787,7 +825,7 @@ ipv6_outstanding_reassembly_perf(int8_t nb_frags, uint8_t fill_order, mbufs[i][0] = buf_out; } - reassembly_print_stats(nb_frags, fill_order, outstanding, + reassembly_print_stats(nb_frags, fill_order, num_exts, outstanding, total_cyc / flow_cnt, total_empty_cyc / frag_processed, total_reassembled_cyc / flow_cnt); @@ -796,7 +834,7 @@ ipv6_outstanding_reassembly_perf(int8_t nb_frags, uint8_t fill_order, } static int -ipv6_reassembly_interleaved_flows_perf(int8_t nb_frags) +ipv6_reassembly_interleaved_flows_perf(int8_t nb_frags, uint8_t num_exts) { struct rte_ip_frag_death_row death_row; uint64_t total_reassembled_cyc = 0; @@ -830,8 +868,8 @@ ipv6_reassembly_interleaved_flows_perf(int8_t nb_frags) struct ipv6_extension_fragment *frag_hdr = rte_pktmbuf_mtod_offset( buf, struct ipv6_extension_fragment *, - buf->l2_len + - sizeof(struct rte_ipv6_hdr)); + buf->l2_len + sizeof(struct rte_ipv6_hdr) + + num_exts * IPV6_ROUTING_HDR_SIZE); tstamp = rte_rdtsc_precise(); buf_out[reassembled] = rte_ipv6_frag_reassemble_packet( @@ -859,7 +897,7 @@ ipv6_reassembly_interleaved_flows_perf(int8_t nb_frags) } } - reassembly_print_stats(nb_frags, FILL_MODE_INTERLEAVED, 0, + reassembly_print_stats(nb_frags, FILL_MODE_INTERLEAVED, num_exts, 0, total_cyc / flow_cnt, total_empty_cyc / frag_processed, total_reassembled_cyc / flow_cnt); @@ -894,25 +932,27 @@ ipv4_reassembly_test(int8_t nb_frags, uint8_t fill_order, uint32_t outstanding) } static int -ipv6_reassembly_test(int8_t nb_frags, uint8_t fill_order, uint32_t outstanding) +ipv6_reassembly_test(int8_t nb_frags, uint8_t fill_order, uint32_t outstanding, + uint8_t num_exts) { int rc; if (nb_frags > 0) - rc = ipv6_frag_pkt_setup(fill_order, nb_frags); + rc = ipv6_frag_pkt_setup(fill_order, nb_frags, num_exts); else - rc = ipv6_rand_frag_pkt_setup(fill_order, MAX_FRAGMENTS); + rc = ipv6_rand_frag_pkt_setup(fill_order, MAX_FRAGMENTS, num_exts); + if (rc) return rc; if (outstanding) rc = ipv6_outstanding_reassembly_perf(nb_frags, fill_order, - outstanding); + outstanding, num_exts); else if (fill_order == FILL_MODE_INTERLEAVED) - rc = ipv6_reassembly_interleaved_flows_perf(nb_frags); + rc = ipv6_reassembly_interleaved_flows_perf(nb_frags, num_exts); else - rc = ipv6_reassembly_perf(nb_frags, fill_order); + rc = ipv6_reassembly_perf(nb_frags, fill_order, num_exts); frag_pkt_teardown(); @@ -925,7 +965,8 @@ test_reassembly_perf(void) int8_t nb_fragments[] = {2, 3, MAX_FRAGMENTS, -1 /* Random */}; uint8_t order_type[] = {FILL_MODE_LINEAR, FILL_MODE_RANDOM}; uint32_t outstanding[] = {100, 500, 1000, 2000, 3000}; - uint32_t i, j; + uint8_t num_exts[] = {0, 4, 8}; + uint32_t i, j, k; int rc; rc = reassembly_test_setup(); @@ -967,32 +1008,40 @@ test_reassembly_perf(void) /* Test variable fragment count and ordering. */ for (i = 0; i < RTE_DIM(nb_fragments); i++) { for (j = 0; j < RTE_DIM(order_type); j++) { - rc = ipv6_reassembly_test(nb_fragments[i], - order_type[j], 0); - if (rc) - return rc; + for (k = 0; k < RTE_DIM(num_exts); k++) { + rc = ipv6_reassembly_test(nb_fragments[i], + order_type[j], 0, num_exts[k]); + if (rc) + return rc; + } } } /* Test outstanding fragments in the table. */ for (i = 0; i < RTE_DIM(outstanding); i++) { - rc = ipv6_reassembly_test(2, 0, outstanding[i]); - if (rc) - return rc; + for (k = 0; k < RTE_DIM(num_exts); k++) { + rc = ipv6_reassembly_test(2, 0, outstanding[i], num_exts[k]); + if (rc) + return rc; + } } for (i = 0; i < RTE_DIM(outstanding); i++) { - rc = ipv6_reassembly_test(MAX_FRAGMENTS, 0, outstanding[i]); - if (rc) - return rc; + for (k = 0; k < RTE_DIM(num_exts); k++) { + rc = ipv6_reassembly_test(MAX_FRAGMENTS, 0, outstanding[i], num_exts[k]); + if (rc) + return rc; + } } /* Test interleaved flow reassembly perf */ for (i = 0; i < RTE_DIM(nb_fragments); i++) { - rc = ipv6_reassembly_test(nb_fragments[i], - FILL_MODE_INTERLEAVED, 0); - if (rc) - return rc; + for (k = 0; k < RTE_DIM(num_exts); k++) { + rc = ipv6_reassembly_test(nb_fragments[i], + FILL_MODE_INTERLEAVED, 0, num_exts[k]); + if (rc) + return rc; + } } reassembly_test_teardown(); diff --git a/lib/ip_frag/ip_frag_common.h b/lib/ip_frag/ip_frag_common.h index 51fc9d47fb..67f5f01c5e 100644 --- a/lib/ip_frag/ip_frag_common.h +++ b/lib/ip_frag/ip_frag_common.h @@ -34,6 +34,8 @@ extern int ipfrag_logtype; #define IPV4_KEYLEN 1 #define IPV6_KEYLEN 4 +#define MAX_NUM_IPV6_EXTS 8 + /* helper macros */ #define IP_FRAG_MBUF2DR(dr, mb) ((dr)->row[(dr)->cnt++] = (mb)) @@ -169,6 +171,8 @@ ip_frag_reset(struct ip_frag_pkt *fp, uint64_t tms) fp->total_size = UINT32_MAX; fp->frag_size = 0; fp->last_idx = IP_MIN_FRAG_NUM; + fp->exts_len = 0; + fp->next_proto = NULL; fp->frags[IP_LAST_FRAG_IDX] = zero_frag; fp->frags[IP_FIRST_FRAG_IDX] = zero_frag; } diff --git a/lib/ip_frag/ip_reassembly.h b/lib/ip_frag/ip_reassembly.h index 54afed5417..689a36ed9a 100644 --- a/lib/ip_frag/ip_reassembly.h +++ b/lib/ip_frag/ip_reassembly.h @@ -51,9 +51,11 @@ struct __rte_cache_aligned ip_frag_pkt { RTE_TAILQ_ENTRY(ip_frag_pkt) lru; /* LRU list */ struct ip_frag_key key; /* fragmentation key */ uint64_t start; /* creation timestamp */ + uint8_t *next_proto; /* pointer of the next_proto field */ uint32_t total_size; /* expected reassembled size */ uint32_t frag_size; /* size of fragments received */ uint32_t last_idx; /* index of next entry to fill */ + uint32_t exts_len; /* length of extension hdrs for first fragment */ struct ip_frag frags[IP_MAX_FRAG_NUM]; /* fragments */ }; diff --git a/lib/ip_frag/rte_ipv6_reassembly.c b/lib/ip_frag/rte_ipv6_reassembly.c index 88863a98d1..fa41bd8e37 100644 --- a/lib/ip_frag/rte_ipv6_reassembly.c +++ b/lib/ip_frag/rte_ipv6_reassembly.c @@ -91,19 +91,19 @@ ipv6_frag_reassemble(struct ip_frag_pkt *fp) /* update ipv6 header for the reassembled datagram */ ip_hdr = rte_pktmbuf_mtod_offset(m, struct rte_ipv6_hdr *, m->l2_len); + payload_len += fp->exts_len; ip_hdr->payload_len = rte_cpu_to_be_16(payload_len); /* * remove fragmentation header. note that per RFC2460, we need to update * the last non-fragmentable header with the "next header" field to contain - * type of the first fragmentable header, but we currently don't support - * other headers, so we assume there are no other headers and thus update - * the main IPv6 header instead. + * type of the first fragmentable header. */ - move_len = m->l2_len + m->l3_len - sizeof(*frag_hdr); - frag_hdr = (struct rte_ipv6_fragment_ext *) (ip_hdr + 1); - ip_hdr->proto = frag_hdr->next_header; + frag_hdr = (struct rte_ipv6_fragment_ext *) + ((uint8_t *) (ip_hdr + 1) + fp->exts_len); + *fp->next_proto = frag_hdr->next_header; + move_len = m->l2_len + m->l3_len - sizeof(*frag_hdr); ip_frag_memmove(rte_pktmbuf_mtod_offset(m, char *, sizeof(*frag_hdr)), rte_pktmbuf_mtod(m, char*), move_len); @@ -112,6 +112,42 @@ ipv6_frag_reassemble(struct ip_frag_pkt *fp) return m; } +/* + * Function to crawl through the extension header stack. + * This function breaks as soon a the fragment header is + * found and returns the total length the traversed exts + * and the last extension before the fragment header + */ +static inline int +ip_frag_get_last_exthdr(struct rte_ipv6_hdr *ip_hdr, uint8_t **last_ext) +{ + uint32_t total_len = 0; + uint8_t num_exts = 0; + size_t ext_len = 0; + *last_ext = (uint8_t *)(ip_hdr + 1); + int next_proto = ip_hdr->proto; + + if (next_proto == IPPROTO_FRAGMENT) + return total_len; + + while (next_proto != IPPROTO_FRAGMENT && num_exts < MAX_NUM_IPV6_EXTS) { + + next_proto = rte_ipv6_get_next_ext(*last_ext, next_proto, &ext_len); + if (next_proto < 0) + break; + + total_len += ext_len; + + if (next_proto == IPPROTO_FRAGMENT) + return total_len; + + *last_ext += ext_len; + num_exts++; + } + + return -1; +} + /* * Process new mbuf with fragment of IPV6 datagram. * Incoming mbuf should have its l2_len/l3_len fields setup correctly. @@ -139,6 +175,8 @@ rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, { struct ip_frag_pkt *fp; struct ip_frag_key key; + uint8_t *last_ipv6_ext; + int exts_len; uint16_t ip_ofs; int32_t ip_len; int32_t trim; @@ -154,10 +192,15 @@ rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, /* * as per RFC2460, payload length contains all extension headers * as well. - * since we don't support anything but frag headers, - * this is what we remove from the payload len. + * so we remove the extension len from the payload len. */ - ip_len = rte_be_to_cpu_16(ip_hdr->payload_len) - sizeof(*frag_hdr); + exts_len = ip_frag_get_last_exthdr(ip_hdr, &last_ipv6_ext); + if (exts_len < 0) { + IP_FRAG_MBUF2DR(dr, mb); + return NULL; + } + + ip_len = rte_be_to_cpu_16(ip_hdr->payload_len) - exts_len - sizeof(*frag_hdr); trim = mb->pkt_len - (ip_len + mb->l3_len + mb->l2_len); IP_FRAG_LOG(DEBUG, "%s:%d:\n" @@ -197,10 +240,24 @@ rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, fp, IPv6_KEY_BYTES(fp->key.src_dst), fp->key.id, fp->start, fp->total_size, fp->frag_size, fp->last_idx); + /* store extension stack info, only for first fragment */ + if (ip_ofs == 0) { + /* + * fp->next_proto points to either the IP's next header + * or th next header of the extension before the fragment + * extension + */ + fp->next_proto = (uint8_t *)&ip_hdr->proto; + if (exts_len > 0) { + fp->exts_len = exts_len; + fp->next_proto = last_ipv6_ext; + } + } /* process the fragmented packet. */ mb = ip_frag_process(fp, dr, mb, ip_ofs, ip_len, MORE_FRAGS(frag_hdr->frag_data)); + ip_frag_inuse(tbl, fp); IP_FRAG_LOG(DEBUG, "%s:%d:\n" -- 2.34.1