From patchwork Wed Aug 19 10:25:29 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eli Britstein X-Patchwork-Id: 2288227 X-Patchwork-Delegate: aconole@redhat.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=Nvidia.com header.i=@Nvidia.com header.a=rsa-sha256 header.s=selector2 header.b=ItWAoSsN; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4hQ2mX6lJZz1xv6 for ; Wed, 19 Aug 2026 20:26:36 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 8E78B80E11; Wed, 19 Aug 2026 10:26:35 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id i22AN4dgJJWR; Wed, 19 Aug 2026 10:26:32 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=140.211.9.56; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= Authentication-Results: smtp1.osuosl.org; dkim=fail reason="signature verification failed" (2048-bit key, unprotected) header.d=Nvidia.com header.i=@Nvidia.com header.a=rsa-sha256 header.s=selector2 header.b=ItWAoSsN Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp1.osuosl.org (Postfix) with ESMTPS id 45B8780E45; Wed, 19 Aug 2026 10:26:31 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 23644C05C8; Wed, 19 Aug 2026 10:26:31 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) by lists.linuxfoundation.org (Postfix) with ESMTP id DEE1BC05D4 for ; Wed, 19 Aug 2026 10:26:29 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id B7E794017C for ; Wed, 19 Aug 2026 10:26:29 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id MJtPF6JDlZg6 for ; Wed, 19 Aug 2026 10:26:27 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=2a01:111:f403:c100::f; helo=bl2pr02cu003.outbound.protection.outlook.com; envelope-from=elibr@nvidia.com; receiver= Authentication-Results: smtp2.osuosl.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com Authentication-Results: smtp2.osuosl.org; dkim=pass (2048-bit key, unprotected) header.d=Nvidia.com header.i=@Nvidia.com header.a=rsa-sha256 header.s=selector2 header.b=ItWAoSsN Received: from BL2PR02CU003.outbound.protection.outlook.com (mail-eastusazlp17011000f.outbound.protection.outlook.com [IPv6:2a01:111:f403:c100::f]) by smtp2.osuosl.org (Postfix) with ESMTPS id 9682F40232 for ; Wed, 19 Aug 2026 10:26:26 +0000 (UTC) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=r9cbNcQNZjYSakKdDSKBrqCSjLn+FVpjf64XI97Xo8BRE96rTtbiJXM8zW+ubyn2qEi64RIQDVKUTqwrvfQKCwfvnEQOp1h/K/2G0QKW4YY24Uxp5Eh6NyGsealJudHdDP0v9MNWBB4Nn/YUuCTwynQ25K2jxDpFmd1juuwOrZoxjAlzKW6O6sP0HVJWKr5j8UjLhCx+nOk3ZPlvQfF7gwAMF64jQKcP6Ntvb+9bbY9bijyUmcA00O0lc8L0l+0V9VgCAtZRrRMoexQXtHOgzq/AcA8GtBewwRpSeexktFYNIVQEDRXY7qNIbiOQLXyRvmC33FpxrddTle8fJTS86A== 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=/gBHnoOG33rp896BVaz9cInrybyWHO6Lt7n/RFwgFR0=; b=Mhtg2iKxgVVr7vHbsB2+UHaMmE8FlunD1kpT8y6LRhpYqqOxEOy+1U3rCBAfjYc/uQbwVfOqHg1tnxX91IYO+B8SDWhy8XFzwnKEIwRoq8vEozlSb+wLjaE3NpUmOS4XCufikC5kJw6FvpSijTCAIjt86AUF2/gDftBCs69CshxrfzEoBF94hOyPun2D4Ie4f8TfbFzU2yklzcXR4zGC7X9gPklScHwOilpH8mAso4D/JXoGoPeiFAm9QmMzt4U7Ob/RJ241zBPASMKmB4k12yfgqgh//iddWr5eGJMrDGgjIpGr93NTibfqrI1D38T8oZ8DVqPwMEEohMnMZ7m6zg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 216.228.117.161) smtp.rcpttodomain=openvswitch.org smtp.mailfrom=nvidia.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=nvidia.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=/gBHnoOG33rp896BVaz9cInrybyWHO6Lt7n/RFwgFR0=; b=ItWAoSsNq08kBLoYkfLqI7ZYSCqZOjvUIj/xaaldzHkWnZ0NYtwofnUBH3DrQNMDPhHKb9pocgy8IGqac0D/E71XnM6EXXYEYK8OuRySMI+2X5hAVc1PtXLpT7LHEup5eB/dtJhFvWMx3eTLGfOVYo3+V0l+Qe5b+hpQSg5QXwG+bDfnVDPU0RSk+WVYulBW4mNVEnKvmz0RC+EtE7aD992fEF2P33NYaVed76Fa0UiHMQyev0hbsUPJQwyEi7Jc6isAt0rb+HarYJoAmH/aiKEHVfhaJwK7JLRm0laQpSiNkzlwXW6XTrW5VIuatKxbHxE95rKBN3/Ymo8FfV2kkg== Received: from PH7P221CA0085.NAMP221.PROD.OUTLOOK.COM (2603:10b6:510:328::19) by SJ0PR12MB7473.namprd12.prod.outlook.com (2603:10b6:a03:48d::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.339.8; Wed, 19 Aug 2026 10:26:19 +0000 Received: from SJ1PEPF000023D5.namprd21.prod.outlook.com (2603:10b6:510:328:cafe::68) by PH7P221CA0085.outlook.office365.com (2603:10b6:510:328::19) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.339.8 via Frontend Transport; Wed, 19 Aug 2026 10:26:19 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 216.228.117.161) smtp.mailfrom=nvidia.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=nvidia.com; Received-SPF: Pass (protection.outlook.com: domain of nvidia.com designates 216.228.117.161 as permitted sender) receiver=protection.outlook.com; client-ip=216.228.117.161; helo=mail.nvidia.com; pr=C Received: from mail.nvidia.com (216.228.117.161) by SJ1PEPF000023D5.mail.protection.outlook.com (10.167.244.70) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.360.0 via Frontend Transport; Wed, 19 Aug 2026 10:26:19 +0000 Received: from rnnvmail201.nvidia.com (10.129.68.8) by mail.nvidia.com (10.129.200.67) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.46; Wed, 19 Aug 2026 03:26:03 -0700 Received: from nvidia.com (10.126.230.37) by rnnvmail201.nvidia.com (10.129.68.8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.20; Wed, 19 Aug 2026 03:26:00 -0700 To: Date: Wed, 19 Aug 2026 13:25:29 +0300 Message-ID: <20260819102529.167827-7-elibr@nvidia.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260819102529.167827-1-elibr@nvidia.com> References: <20260819102529.167827-1-elibr@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.126.230.37] X-ClientProxiedBy: rnnvmail201.nvidia.com (10.129.68.8) To rnnvmail201.nvidia.com (10.129.68.8) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: SJ1PEPF000023D5:EE_|SJ0PR12MB7473:EE_ X-MS-Office365-Filtering-Correlation-Id: 6376e4c9-2a55-4857-3b1d-08defddc4ed7 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|82310400026|376014|36860700016|1800799024|23010399003|10067099003|56012099006|3023799007|22082099003|18002099003|11063799006; X-Microsoft-Antispam-Message-Info: QpfjpCpHuwdIQQ9MTAYy8S7S6c36U2Z/532O/RdW1YbX/UDwgStLMAGljlIP6y9XZlYmFPacWrfmaREA2f8dW2IPKfWXoflv1WTEED3QwFlxJGT82RbDS9DJppW7KPKLx6PZgWenUUAxe/Iiykp6NQsY1n+TOHfuIL/Bra0EDjeNTLHuCwTbsXtF1ASoqaQOzt/46Nr1MF6OWWjSsUnnVyI42N5jsJADwqxj+BSdK8xk+Q2TvjM21T9yC6QVNSA2ngmICWgbiFrY86dPt7nFCf6CtmO8sk/HlnnYDDRIosAz8ijBCA9UgJpGjUMwxPtlQNNIrEDJngQyhwQxmAEzXLigYrCKEe5OFrWe8Mt9oKgsiZT3otDCmXshJApQfnHieq6aJzWIOX7fqzXuqg6Cxxqg1nBdzE+/HpVsf+jV6Y2FSJjRWML1Zb2neYVhiGt1BjVZya5v3ETauyme3Qp6D1B0DzOV+jxNuF/JKLBOf3EdTNJzrJi7v5WukxXQqAlLndEezuwDrMBBR51fkAHB515kr1Wz6bw8S/QLrh3qKYeNc698QVHRFZAIP0zcd9vCzCc+XLsymf59KRmJcQpJxDlDY1Vt2VmCnsLkjc/FBmfZia5dYVCrazUaDrbJXHv0eomyGT/5IGAhzjo6rlnHsyDYBoprakZbD0fwMBJHmxY= X-Forefront-Antispam-Report: CIP:216.228.117.161; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:mail.nvidia.com; PTR:dc6edge2.nvidia.com; CAT:NONE; SFS:(13230040)(82310400026)(376014)(36860700016)(1800799024)(23010399003)(10067099003)(56012099006)(3023799007)(22082099003)(18002099003)(11063799006); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: i43nkzpwsOcb1N2XH9XU/F8fErK6aOIZEExWeG0LXdj2lSKAJgC6hCCzrS4EIXaB+cK8fPEgb2kqAgshWjCB5ZVDWQUl+8kfoW/BkT/WWkLXEatlL+jMxejHxgxN0sLc7Pyp8GC9JJDpNWdaycOe9TAVSZ3d1DJVWM2p8eJmhgRC+zn15hoPe+prdmO65X39Q6ZjHEu3+bHmZE5U0jAVaG7LXnUustPrR0PTj7o2VPqMwYd5oxsz5vZcamNOaQNanstHS+VXVYjcZKWtJy7ZKiXCffVHLAc7J3x0mWXkb4gXnPpGgZY/72xoloV+NjK9HDkU2AOvaxSMc/j1hJZYn5W8iurrNGTlICl9qrGyigfaFXAudhQNsOzRDMXMmGR5ehyi/YPimIr/m2bOZEAH9gQvDxs2hfAJgOsQQGCVjs3IsSE4q92tr8tUFrnifyLi X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Aug 2026 10:26:19.0184 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 6376e4c9-2a55-4857-3b1d-08defddc4ed7 X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a; Ip=[216.228.117.161]; Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-AuthSource: SJ1PEPF000023D5.namprd21.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: SJ0PR12MB7473 Subject: [ovs-dev] [PATCH v5 6/6] ipf: Reject fragments beyond the last fragment. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Eli Britstein via dev From: Eli Britstein Reply-To: Eli Britstein Cc: Eli Britstein , Ilya Maximets , Alin Serdean , Maor Dickman Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" IP reassembly must not accept data past an MF=0 fragment. Track last fragments, reject ranges beyond them on insert, and require the sorted rightmost fragment to be MF=0 before completing a list. The accompanying test is added to tests/ofproto-dpif.at (using netdev-dummy/receive with variable-built packets and precomputed IPv4 header checksums) rather than the system-traffic suite. Assisted-by: composer-2.5-fast, Cursor Fixes: 4ea96698f667 ("Userspace datapath: Add fragmentation handling.") Signed-off-by: Eli Britstein --- lib/dpctl.c | 4 ++ lib/dpif-provider.h | 1 + lib/ipf.c | 48 +++++++++++++++++++-- lib/ipf.h | 1 + tests/ofproto-dpif.at | 74 ++++++++++++++++++++++++++++++++ tests/system-userspace-macros.at | 8 ++++ 6 files changed, 133 insertions(+), 3 deletions(-) diff --git a/lib/dpctl.c b/lib/dpctl.c index 48afb8549..b147853ca 100644 --- a/lib/dpctl.c +++ b/lib/dpctl.c @@ -2629,6 +2629,8 @@ dpctl_ct_ipf_get_status(int argc, const char *argv[], dpif_ipf_status.v4.nfrag_too_large); dpctl_print(dpctl_p, " v4 frags overlapped: %"PRIu64"\n", dpif_ipf_status.v4.nfrag_overlap); + dpctl_print(dpctl_p, " v4 frags beyond last: %"PRIu64"\n", + dpif_ipf_status.v4.nfrag_beyond_last); dpctl_print(dpctl_p, " v4 frags purged: %"PRIu64"\n", dpif_ipf_status.v4.nfrag_purged); @@ -2646,6 +2648,8 @@ dpctl_ct_ipf_get_status(int argc, const char *argv[], dpif_ipf_status.v6.nfrag_too_large); dpctl_print(dpctl_p, " v6 frags overlapped: %"PRIu64"\n", dpif_ipf_status.v6.nfrag_overlap); + dpctl_print(dpctl_p, " v6 frags beyond last: %"PRIu64"\n", + dpif_ipf_status.v6.nfrag_beyond_last); dpctl_print(dpctl_p, " v6 frags purged: %"PRIu64"\n", dpif_ipf_status.v6.nfrag_purged); } else { diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h index b3dd58e9d..6f667fed1 100644 --- a/lib/dpif-provider.h +++ b/lib/dpif-provider.h @@ -131,6 +131,7 @@ struct dpif_ipf_proto_status { uint64_t nfrag_too_small; uint64_t nfrag_too_large; uint64_t nfrag_overlap; + uint64_t nfrag_beyond_last; uint64_t nfrag_purged; unsigned int min_frag_size; bool enabled; diff --git a/lib/ipf.c b/lib/ipf.c index 2b016e60b..1a16908c7 100644 --- a/lib/ipf.c +++ b/lib/ipf.c @@ -84,6 +84,7 @@ enum ipf_counter_type { IPF_NFRAGS_TOO_SMALL, IPF_NFRAGS_TOO_LARGE, IPF_NFRAGS_OVERLAP, + IPF_NFRAGS_BEYOND_LAST, IPF_NFRAGS_PURGED, IPF_NFRAGS_NUM_CNTS, }; @@ -98,6 +99,7 @@ struct ipf_frag { struct dp_packet *pkt; uint16_t start_data_byte; uint16_t end_data_byte; + bool last_frag; /* True if this was the MF=0 fragment. */ }; /* The key for a collection of fragments potentially making up an unfragmented @@ -397,8 +399,14 @@ ipf_list_complete(const struct ipf_list *ipf_list) != ipf_list->frag_list[i].start_data_byte) { return false; } + + /* Only the final fragment may have MF=0; data past it is invalid. */ + if (ipf_list->frag_list[i - 1].last_frag) { + return false; + } } - return true; + + return ipf_list->frag_list[ipf_list->last_inuse_idx].last_frag; } /* Runs O(n) for a sorted or almost sorted list. */ @@ -859,6 +867,28 @@ ipf_is_frag_duped(const struct ipf_frag *frag_list, int last_inuse_idx, return false; } +/* Returns true if accepting this fragment would place data past an MF=0 + * (last) fragment, which is illegal for IP reassembly. */ +static bool +ipf_is_beyond_last_frag(const struct ipf_frag *frag_list, int last_inuse_idx, + uint16_t start_data_byte, uint16_t end_data_byte, + bool lf) + /* OVS_REQUIRES(ipf_lock) */ +{ + for (int i = 0; i <= last_inuse_idx; i++) { + if (frag_list[i].last_frag + && start_data_byte > frag_list[i].end_data_byte) { + return true; + } + + if (lf && frag_list[i].end_data_byte > end_data_byte) { + return true; + } + } + + return false; +} + /* Adds a fragment to a list of fragments, if the fragment is not a * duplicate. If the fragment is a duplicate, the fragment is dropped * to avoid the work that conntrack would do to mark the fragment @@ -872,14 +902,17 @@ ipf_process_frag(struct ipf *ipf, struct ipf_list *ipf_list, { bool duped_frag = ipf_is_frag_duped(ipf_list->frag_list, ipf_list->last_inuse_idx, start_data_byte, end_data_byte); + bool beyond_last = ipf_is_beyond_last_frag(ipf_list->frag_list, + ipf_list->last_inuse_idx, start_data_byte, end_data_byte, lf); int last_inuse_idx = ipf_list->last_inuse_idx; - if (!duped_frag) { + if (!duped_frag && !beyond_last) { if (last_inuse_idx < ipf_list->size - 1) { struct ipf_frag *frag = &ipf_list->frag_list[last_inuse_idx + 1]; frag->pkt = pkt; frag->start_data_byte = start_data_byte; frag->end_data_byte = end_data_byte; + frag->last_frag = lf; ipf_list->last_inuse_idx++; atomic_count_inc(&ipf->nfrag); ipf_count(ipf, v6, IPF_NFRAGS_ACCEPTED); @@ -887,11 +920,16 @@ ipf_process_frag(struct ipf *ipf, struct ipf_list *ipf_list, } else { OVS_NOT_REACHED(); } - } else { + } else if (duped_frag) { ipf_count(ipf, v6, IPF_NFRAGS_OVERLAP); dp_packet_delete(pkt); return true; + } else { + ipf_count(ipf, v6, IPF_NFRAGS_BEYOND_LAST); + dp_packet_delete(pkt); + return true; } + return true; } @@ -1486,6 +1524,8 @@ ipf_get_status(struct ipf *ipf, struct ipf_status *ipf_status) &ipf_status->v4.nfrag_too_large); atomic_read_relaxed(&ipf->n4frag_cnt[IPF_NFRAGS_OVERLAP], &ipf_status->v4.nfrag_overlap); + atomic_read_relaxed(&ipf->n4frag_cnt[IPF_NFRAGS_BEYOND_LAST], + &ipf_status->v4.nfrag_beyond_last); atomic_read_relaxed(&ipf->n4frag_cnt[IPF_NFRAGS_PURGED], &ipf_status->v4.nfrag_purged); @@ -1504,6 +1544,8 @@ ipf_get_status(struct ipf *ipf, struct ipf_status *ipf_status) &ipf_status->v6.nfrag_too_large); atomic_read_relaxed(&ipf->n6frag_cnt[IPF_NFRAGS_OVERLAP], &ipf_status->v6.nfrag_overlap); + atomic_read_relaxed(&ipf->n6frag_cnt[IPF_NFRAGS_BEYOND_LAST], + &ipf_status->v6.nfrag_beyond_last); atomic_read_relaxed(&ipf->n6frag_cnt[IPF_NFRAGS_PURGED], &ipf_status->v6.nfrag_purged); return 0; diff --git a/lib/ipf.h b/lib/ipf.h index 2ac3c9658..59ae887c3 100644 --- a/lib/ipf.h +++ b/lib/ipf.h @@ -29,6 +29,7 @@ struct ipf_proto_status { uint64_t nfrag_too_small; uint64_t nfrag_too_large; uint64_t nfrag_overlap; + uint64_t nfrag_beyond_last; uint64_t nfrag_purged; unsigned int min_frag_size; bool enabled; diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at index 0ff4c50f8..032707dd5 100644 --- a/tests/ofproto-dpif.at +++ b/tests/ofproto-dpif.at @@ -5842,6 +5842,80 @@ AT_CHECK([ovs-appctl dpctl/ipf-get-status -m \ OVS_VSWITCHD_STOP AT_CLEANUP +AT_SETUP([ofproto-dpif - fragment handling - reject fragment beyond last]) +OVS_VSWITCHD_START +add_of_ports br0 1 90 + +AT_DATA([flows.txt], [dnl +table=0 in_port=90,ip actions=ct(commit),output:1 +]) +AT_CHECK([ovs-ofctl -O OpenFlow11 replace-flows br0 flows.txt]) + +dnl The minimum fragment size is clamped to 400 bytes, so a non-last fragment +dnl must be at least that large to be admitted for reassembly. +AT_CHECK([ovs-appctl dpctl/ipf-set-min-frag v4 400], [], [dnl +setting minimum fragment size successful +]) + +dnl First admit a last (MF=0) fragment carrying bytes 400..799, then reject a +dnl new fragment carrying bytes 800..1199, whose data lies entirely beyond the +dnl end of the last fragment and so must not be reassembled. +dnl +dnl Packet 1 (admitted). Last fragment carrying bytes 400..799 (MF clear). +dnl Ethernet II, Src: 50:54:00:00:00:09, Dst: 50:54:00:00:00:0a +dnl Type: IPv4 (0x0800) +dnl Internet Protocol Version 4, Src: 10.1.1.1, Dst: 10.1.1.2 +dnl 0100 .... = Version: 4 +dnl .... 0101 = Header Length: 20 bytes (5) +dnl Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT) +dnl Total Length: 420 +dnl Identification: 0x0020 (32) +dnl 000. .... = Flags: 0x0 (Last fragment) +dnl ...0 0000 0011 0010 = Fragment Offset: 400 +dnl Time to Live: 64 +dnl Protocol: UDP (17) +dnl Header Checksum: 0x62f3 +dnl Data (400 bytes) +eth="50 54 00 00 00 0a 50 54 00 00 00 09 08 00" +ip1="45 00 01 a4 00 20 00 32 40 11 62 f3" +addrs="0a 01 01 01 0a 01 01 02" +data1=$(printf '%0*d' 800 0) +packet1="${eth}${ip1}${addrs}${data1}" + +dnl Packet 2 (rejected as beyond last). Fragment carrying bytes 800..1199 +dnl (MF set), starting past packet 1's last-fragment end. +dnl Ethernet II, Src: 50:54:00:00:00:09, Dst: 50:54:00:00:00:0a +dnl Type: IPv4 (0x0800) +dnl Internet Protocol Version 4, Src: 10.1.1.1, Dst: 10.1.1.2 +dnl 0100 .... = Version: 4 +dnl .... 0101 = Header Length: 20 bytes (5) +dnl Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT) +dnl Total Length: 420 +dnl Identification: 0x0020 (32) +dnl 001. .... = Flags: 0x1 (More fragments) +dnl ...0 0000 0110 0100 = Fragment Offset: 800 +dnl Time to Live: 64 +dnl Protocol: UDP (17) +dnl Header Checksum: 0x42c1 +dnl Data (400 bytes) +ip2="45 00 01 a4 00 20 20 64 40 11 42 c1" +data2=$(printf '%0*d' 800 0) +packet2="${eth}${ip2}${addrs}${data2}" + +AT_CHECK([ovs-appctl netdev-dummy/receive p90 "$packet1"]) +AT_CHECK([ovs-appctl netdev-dummy/receive p90 "$packet2"]) + +AT_CHECK([ovs-appctl dpctl/ipf-get-status -m \ +| grep -E 'num frag:|v4 frags accepted:|v4 frags completed:|v4 frags beyond last:'], [], [dnl + num frag: 1 + v4 frags accepted: 1 + v4 frags completed: 0 + v4 frags beyond last: 1 +]) + +OVS_VSWITCHD_STOP +AT_CLEANUP + AT_SETUP([ofproto-dpif - handling of malformed TCP packets]) OVS_VSWITCHD_START add_of_ports br0 1 90 diff --git a/tests/system-userspace-macros.at b/tests/system-userspace-macros.at index 10ce3e746..3579718f8 100644 --- a/tests/system-userspace-macros.at +++ b/tests/system-userspace-macros.at @@ -180,6 +180,7 @@ AT_CHECK([ovs-appctl dpctl/ipf-get-status], [], [dnl v4 frags too small: 0 v4 frags too large: 0 v4 frags overlapped: 0 + v4 frags beyond last: 0 v4 frags purged: 0 min v6 frag size: 1280 v6 frags accepted: 0 @@ -188,6 +189,7 @@ AT_CHECK([ovs-appctl dpctl/ipf-get-status], [], [dnl v6 frags too small: 0 v6 frags too large: 0 v6 frags overlapped: 0 + v6 frags beyond last: 0 v6 frags purged: 0 ]) ]) @@ -212,6 +214,7 @@ AT_CHECK([ovs-appctl dpctl/ipf-get-status --more], [], [dnl v4 frags too small: 0 v4 frags too large: 0 v4 frags overlapped: 0 + v4 frags beyond last: 0 v4 frags purged: 0 min v6 frag size: 1280 v6 frags accepted: 0 @@ -220,6 +223,7 @@ AT_CHECK([ovs-appctl dpctl/ipf-get-status --more], [], [dnl v6 frags too small: 0 v6 frags too large: 0 v6 frags overlapped: 0 + v6 frags beyond last: 0 v6 frags purged: 0 Fragment Lists: @@ -247,6 +251,7 @@ AT_CHECK([ovs-appctl dpctl/ipf-get-status --more], [], [dnl v4 frags too small: 0 v4 frags too large: 0 v4 frags overlapped: 0 + v4 frags beyond last: 0 v4 frags purged: 0 min v6 frag size: 1280 v6 frags accepted: 30 @@ -255,6 +260,7 @@ AT_CHECK([ovs-appctl dpctl/ipf-get-status --more], [], [dnl v6 frags too small: 0 v6 frags too large: 0 v6 frags overlapped: 0 + v6 frags beyond last: 0 v6 frags purged: 0 Fragment Lists: @@ -289,6 +295,7 @@ AT_CHECK([ovs-appctl dpctl/ipf-get-status -m | FORMAT_FRAG_LIST()], [], [dnl v4 frags too small: 0 v4 frags too large: 0 v4 frags overlapped: 0 + v4 frags beyond last: 0 v4 frags purged: 0 min v6 frag size: 1280 v6 frags accepted: 0 @@ -297,6 +304,7 @@ AT_CHECK([ovs-appctl dpctl/ipf-get-status -m | FORMAT_FRAG_LIST()], [], [dnl v6 frags too small: 0 v6 frags too large: 0 v6 frags overlapped: 0 + v6 frags beyond last: 0 v6 frags purged: 0 Fragment Lists: