From patchwork Sat Aug 24 09:27:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Kshevetskiy X-Patchwork-Id: 1976358 X-Patchwork-Delegate: pbrobinson@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.a=rsa-sha256 header.s=selector2 header.b=N3/z7/oj; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (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 4WrWnL6mwyz1yXd for ; Sat, 24 Aug 2024 19:27:50 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 102BB88C13; Sat, 24 Aug 2024 11:27:33 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.b="N3/z7/oj"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 9B4B188BE4; Sat, 24 Aug 2024 11:27:31 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,SPF_HELO_PASS, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 Received: from EUR05-AM6-obe.outbound.protection.outlook.com (mail-am6eur05on2071e.outbound.protection.outlook.com [IPv6:2a01:111:f403:2612::71e]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 6C59788966 for ; Sat, 24 Aug 2024 11:27:28 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mikhail.kshevetskiy@genexis.eu ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=aOWPXeaD5rgjbxzgm8GSEejBITz15omkFI28bMulL5muAEdcaC4c4DAmbQQ6MxK4Eve4/okIWLoe1hXDwQCQaAeQddDq/XFca0rbXEAsx4RqXOoK1dgpoZz/4xELVz03162DrOZAYs9qyBGaahj5Ad1ifSR8GprkX5JOFDCiglQaB2ENQTxpclBHOlm8QjuwBDa2bq8zhCiBBa787RHOfsL3Gf42nNnKbCu38p7t1opEOIOAIWrakWOfO1eVjQSx6LZJlDE/BpeBITxfUw6emzoOBqs/2N2pnMgaxmzgW+6i+6ww0ncRiGZ5UkumB7RdaKlsmzr1/75i2y8SA+ysCw== 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=/5LDNcV6ld1fkkvGz+Av9Zyvf4dlWpsdwbEWmCK0F2Y=; b=nd82ORrhh8Eu0+1NRU4ThLZKhQn71FIxAaSOO3We4MyN4FKPwOuEmG+WO+MktLyr8gxaPjqnpML8hZ2riayhkSc7UHmXmTAfgQkK7MEZDWkDolXVBQ9KRUhHXALkRnfzZcL0JaBEsg9uaUZD8Vaotrl4n0HFaj0qVcG/ZekB1Kx9HSTmL1epiOQSfs8xXuIU+03lvLSgbicoFxkss2VEOo+gAalfKvA7ENYQcEgjtcDzuRJevVRwqDSM1Qb9uNCoqxjlJJ6Q8XgbuowMiRkFeVfWfgM3e2IzBTg7BHFfJVJpb+tczejqh6SD7mzpjPYltPaR+g6Stla+SWNsZyrfbA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=genexis.eu; dmarc=pass action=none header.from=iopsys.eu; dkim=pass header.d=iopsys.eu; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iopsys.eu; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=/5LDNcV6ld1fkkvGz+Av9Zyvf4dlWpsdwbEWmCK0F2Y=; b=N3/z7/oj2Ff1hjdbylKA7b9m+laS2j+8VHX6+UbdRQ3W002+ZaHCoo27WdpXmSt9K9bkwhmsOgYqj7sAOTMVHw41AG6Br2pIVgYVYxlYQndyzfGQyMj1vExPFBi50PP+1UJ90gOXA1tpgg6KCDXwVlGO2nVzPnO8mB3DrKJVLblPffXAzZau6m0POSg9Af0bm967p72u8YGtwCXPmb18tfHCeAEjJLTBOgUhwK1dTErU8UA4M1X0/a4xLY0mIOuPBekKFPxVyLFB4a3evxhydW8/4f0/ffpeuntX8fE35+TAfeppuCGzHjY7B7zYYtyoTZDfZCksOjQUYa/uauiKDA== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=iopsys.eu; Received: from GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) by AS4PR08MB7601.eurprd08.prod.outlook.com (2603:10a6:20b:4ff::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7897.18; Sat, 24 Aug 2024 09:27:27 +0000 Received: from GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0]) by GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0%2]) with mapi id 15.20.7918.011; Sat, 24 Aug 2024 09:27:27 +0000 From: Mikhail Kshevetskiy To: Tom Rini , Joe Hershberger , Ramon Fried , Mattijs Korpershoek , Simon Glass , Heinrich Schuchardt , AKASHI Takahiro , Michal Simek , Francis Laniel , Anand Moon , Mikhail Kshevetskiy , Marek Vasut , Ilias Apalodimas , Masahisa Kojima , Sean Anderson , Baruch Siach , Yasuharu Shibata , u-boot@lists.denx.de Subject: [PATCH v5 01/11] net/tcp: fix TCP options processing Date: Sat, 24 Aug 2024 12:27:06 +0300 Message-ID: <20240824092716.1042696-2-mikhail.kshevetskiy@iopsys.eu> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240824092716.1042696-1-mikhail.kshevetskiy@iopsys.eu> References: <20240824092716.1042696-1-mikhail.kshevetskiy@iopsys.eu> X-ClientProxiedBy: GV3P280CA0011.SWEP280.PROD.OUTLOOK.COM (2603:10a6:150:b::7) To GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: GV2PR08MB8121:EE_|AS4PR08MB7601:EE_ X-MS-Office365-Filtering-Correlation-Id: 4827e34a-f1ab-4a1a-6165-08dcc41ef80d X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|366016|376014|1800799024|52116014|7416014|921020|38350700014; X-Microsoft-Antispam-Message-Info: 8CWHolRh+dh/QI5igRlYuKJ5iMZ/PwC4gIetMwpq/lQEpzR0FqS78nlokI1Z0uNp4iGD2Au5aZD/hhQutXCsbCEfGpdnQc9vQ/141HB93oEDh38V6yZsUrvjfbutXUc5pUc7ogw3octQVThcmclH9EGLHO9nsfbsumuQCyGcy8+oS4f/gw1Oe4QYDa7nnEWiGI7JSIAJEgU0TVnZmPkvE2+mn0MZPQkz0FDoTABdLJ9UqPV/T0KPfEKltKU3/Um4ZEYVwSgBqZ8HRD/TbwNB3rQhoZWPs8TTOf+fRcYyZWKg6lCizzw/VkhDcFXRuDB80EnLatxg6dC/42s3vZ70Mm1oxhJMVEd4rUuj6fE3Rwn1nIUz0CYHoT38m5KtD3cVDNR60GM4XXsG5qJBEFqXmE9oYn6NUmad8puFBJqk/oQisP3oeF0hKBp+vpuGx883EGVbpIOy5U0fneNTM9o48oJKxzahqTpo7B229CB6NdfblggO9+tufGnt8/ucbuty/P82W5qLfjIgYlmHpOCfbI7WHYsSPw9rqNJjSy4cHI9gmhUeMlbKWM3ifXmudM/w6NQ8nIo0e2N1kmXOTGvC62ZJxYGdbiwndbLHjaIJNq/JL/lu8RpCrfd3mgOk/NpQYvGHy2A9Gl9idrfO5gXVd6cBOiN2M5dpWLF51DkZoT1Ns42fzuCRGmCZBPq47i3BMzbXYMbcjosve3yL5+1llD3ZGG9zT1Dknat1ignCo2uWWuKFqql0we1Mc+Y+a5AChGVc2L+geNpQoDGAuFg45x5uHKyBfKzOyK83IOkh6/lYp3iNZCWlC8l+XjF00e3JQnZnZ8UxVcve6YUH9XqMEh9oHvCLGNSN5bRXEvTQO3bJe2sUUaB0p6kaxF550kHpZ1ICfbZy3rgbgOFgtTrymo/U3T3+cePFH01cPWKsxiqSx2CYGskLLKS/Jja9RbJhi4BBroi205Q8/QoEqpvBYpTZfRlg4RNQ4Ga6S5jo8crSbh/x36k+7MvyPe9lpYbnlzft9EZqqSowutRd53qI3xFpVIcwrLKcd9SgPVfXsS4R4s6zyUTANLTm334gNI+f1Xn0HcXEKfjfq/gz3ELHnjF9jD/kkyTXdw1ht3fZt/BrUbiGX4EesgL7OeGhjEQ1yC7W5yAs9FHQLDeZicivr0aN+Wp9EPrN7t0WkpaeCdQGxyXk7euOuXdKKp0bA5izDruUI/FePFmyY9fT0ritOx5whtIG31oVRtEYhlSqf6WNBvM1hALseWr2LPG2sa8OiwqPYjXkE7uK9y9b3j+3T7xHq7Igr5ua8ouEnNjC1HhlGmHoYRtgpvKbSPkgsTqRSnAkmuZvA+S1XfvsIDyucoBk69mQ94rIaR0dNj/V078M9mtCZcfYyE3LadTq2mcff8BIp3BC+j/Hep8g4qaq/r6hMpqJBegx4UeBgrK0FJ8= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:GV2PR08MB8121.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(366016)(376014)(1800799024)(52116014)(7416014)(921020)(38350700014); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: l8PnsJ4KdLC0E9jzlHTr9GtFWeE00ECa8KGxZ34cKezyphSQxCHb+JA5HM97Lg+tJF56/Q/s5bOO57EJZ1x/APcIO12fCqnxSay016X7FDn/k8lW6aNb5kP95In8G9t+hyG7M4ywMBhqOYwoPoZgqiTng/zCwrU/J8W09PsSrI3r5kRtDyu7c/z20v95eARQPJRvR9PGYXroXaPNVNe0C/1kzi6IUGSEyqS915OSinLRHvRR1AtziT7tiMF2HUeZATArFAEm3pYVMPmYjAD7VhoeMsBk0aPYKeluxMZUZnFPe1ohJ9gCKHywtiCzvLiQzQkrHaNS6gpxO8IN0c83ZMQ1AXk3hOKwc3vPHKAHVScy0xYS0APSTy+oRjEvhtTnx5qiCKAYjGjAhKitOpV964vveYiRLpggzvs+b10dLk/4GMeRZaljqmEAgzUTPX84v1jg4J2/qc7cMY2R0yZsnsBaYUYBqVE0Z4A5bK0pJ+Ty5Z3N+b0xHwSLyZdcVBSg5YWDy9YgMgAnVaemg5+ovDSNX8kHYL+5nlVyVSfwGhmm9maWOmB4Um9fBwEU6VAVs3Z88F0J4DakFJNCM1lWoo61DH0+UaHJzJaIdWKvEKiAyo+/rdgfhA1bdhfaQZQLtlhCwTBuysXLXqoO6Fs40iQMyECHajq8VbagzB/i30NKEoEXP3ia/N3N6XQjP85KmKSK62y1NrKk/MRD7AXnT62KclYepemwQ0p3Rsz4GBROOF/DIyVWpOEJdzNWaEeIHjrVbcTto1MIwgCywT/ed2zgKOI6HZksibC1YoETMSieeAT7PRT4jVE1PkuNXkYvzjSP8TI/OP2QsMntiKzyD6AoSskJYnDyYzwy2J8+rBoY3Q3ZadJfFQToGeb5VVLaiboHmrTFJd2Rf9E1SmNX2SOFogm4ShRRsgw7ut4peQMnKPIrh1FdX5d8+suyEE/xXWypceGAb3DquAlBag3ry6WFr5d0FOZQy21Bv2C7NuKluF1GrOzdZ84S4j21VgVc/V6g1R/jCnDZ8zWpYv3YuMmTI/JQEkqCBEPlKgDTamBZBXuwhefceeQ+T635/nUZkhJWm/gUTz4ix3+ooQBTOzxOdOJdeg7t4Kr9MfZE/o9xaRHbHNgcbmDsPdO1oS4U8HQq5gMghZoHkhNzniiaNchHKKiKAomjX5LOeju4cjwClrKzqYJxkPGPq/l3ZEEmKGtWK0OlikbBMclv/GhMgrpqvOyPncgWuSKc655Wh3aizLWAgHR7UTgxbM4LREvuaN5hJukAoqtq7SSZDWsjN9PL27nRdIeybzExhcYb//HjBS+Anife83pDdhNIi90xGzpl+3U+SRHpAcnEPqst3zn/5Jfk4ICCeyNv5XQ9ylVAoW9tE6d6YScSG8tYgxruOKOLOPkeOwNv1xZ9vnm6lQuB707q//n0tAerO7NGpi89SqzsD7kEVYHQYXhim4Z/8iiU4IxUBRXh9cVU4CgExmICE7iuUsmJGsANmLRaljzIMPSE/ZrClTdeZN+qq+PHiz0oasCfEs/cordDXtVKcr1L7MNdXVFuXqZeYzdzPeVBinR03kD29KRSNVEAFXHPTg9bRA9LYUPD0oIPevA/Uv8WTbDkd5/yuo96XSvNIdY= X-OriginatorOrg: iopsys.eu X-MS-Exchange-CrossTenant-Network-Message-Id: 4827e34a-f1ab-4a1a-6165-08dcc41ef80d X-MS-Exchange-CrossTenant-AuthSource: GV2PR08MB8121.eurprd08.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Aug 2024 09:27:27.1005 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 8d891be1-7bce-4216-9a99-bee9de02ba58 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: y5IQnLhWNLNqq0tOpwSNBK7jAQEWZWjCAzTnvCxw07Z6h8eXDNZhvKYa1mdRAykogcdDMSuPUbX/sOIwiqAPOq+lj26SuIzepOgjAhu5wQ4= X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS4PR08MB7601 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Current TCP code may miss an option if TCP_O_NOP option was used before it for proper aligning. Signed-off-by: Mikhail Kshevetskiy Reviewed-by: Simon Glass --- net/tcp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/tcp.c b/net/tcp.c index b0cc8a1fe3e..3e3118de450 100644 --- a/net/tcp.c +++ b/net/tcp.c @@ -475,7 +475,7 @@ void tcp_parse_options(uchar *o, int o_len) * NOPs are options with a zero length, and thus are special. * All other options have length fields. */ - for (p = o; p < (o + o_len); p = p + p[1]) { + for (p = o; p < (o + o_len); ) { if (!p[1]) return; /* Finished processing options */ @@ -490,12 +490,14 @@ void tcp_parse_options(uchar *o, int o_len) case TCP_O_TS: tsopt = (struct tcp_t_opt *)p; rmt_timestamp = tsopt->t_snd; - return; + break; } /* Process optional NOPs */ if (p[0] == TCP_O_NOP) p++; + else + p += p[1]; } } From patchwork Sat Aug 24 09:27:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Kshevetskiy X-Patchwork-Id: 1976359 X-Patchwork-Delegate: pbrobinson@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.a=rsa-sha256 header.s=selector2 header.b=X6kM6vbs; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WrWnS54zVz1yXd for ; Sat, 24 Aug 2024 19:27:56 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 6DC5B88C47; Sat, 24 Aug 2024 11:27:33 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.b="X6kM6vbs"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 0DB0088C10; Sat, 24 Aug 2024 11:27:32 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,SPF_HELO_PASS, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05on20727.outbound.protection.outlook.com [IPv6:2a01:111:f403:2613::727]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id E776F888FD for ; Sat, 24 Aug 2024 11:27:29 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mikhail.kshevetskiy@genexis.eu ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=RYAuII0KO+oSY280OMHEY+PsChYmnOU88ruYl3MX9Q2+pe86siit5vi4v59pTemFtXSI9dV0WzsTXIV25h0EQ9hnxWaI+31Ws3esDe4007ImAjGVZxcAhTWNjcJ5ufxsD3riI+ka5zuFwTQ2OcgY6wHfSJkUKr6MEKP3KdGUPmmhsx+NEOhx4H7A98+VK8TdVKhxDdwe/cjUH4awXGonNs3IWgzRpMvuzE60qJTSrKb3eB1JLTDJee/Vkplz0ikVTjvqdKPWX+ZljKWTM8JkgTTc+lOQvBdu6uL42pZsPKad4Wnojo+SCwMXgxXJiwSehCwD30j0/YV+Aqkg7tEDsQ== 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=hahBnFJbV0odlIPukazF5oQypFtjvGWCc6V4kSoQSX0=; b=rRetZs1x4KVQIQ54O4WS19jIf/qJEoUaHcGRrrn/cHBiz2zsosNS+gXeztChBnprzZvXuld+3XB2BxQRpBUT4wE06BKB0q6aIJvwknPEI/Q1hoqcyhKrhSZVx0Mz50rf7ihJMq2VLuCU0KkZ1xgYrQQZaO+B4EYG2QVQmMpFrvJJM6KI3k/keFSns2e80q1+y749ibrt7PWLdzcKwLUbDUGOZXmpRNps8fyHSvzaBgR1LnIq5F23sxf1bZbBXtmdJ2H+dzQUAO76CiUpAbE4caaYuIGS+fyZ6xdpWYa87WFtk8Jokx8tj4h4fe8U02ywEI99Q6ZRFQbrz4yI5mCltw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=genexis.eu; dmarc=pass action=none header.from=iopsys.eu; dkim=pass header.d=iopsys.eu; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iopsys.eu; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=hahBnFJbV0odlIPukazF5oQypFtjvGWCc6V4kSoQSX0=; b=X6kM6vbsTB1GKbV1Sbnda7iRec0gQgo5St8eHzPDtc1JYMggBsbbQFogIR/dNpXhVDF1lATvHv/Z7qE3wG23Rp5m3fYGQ9PTSkUjOPRsvl5njWOMyIgUDgUJ10fDzbAq/LXXQAcFW0oLF7RSOlBp1Nur9IeWSXVkQmfC09alq+4vkPe7XaHLZbnXnaXwXQwgj2x/rLjEeD8r5+CSapwlZ/F+MoSKRBEXT0d0+uB2TAcFiufy98SiouDW8Tz3m8vqu684OwjztD13WDipGtTNg6/0JGrKr0BgjdKiI6DsSNtFCPPGJJ2vk9RiIs43mhVgfiSy8Uh6p2JRND/0/G40XQ== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=iopsys.eu; Received: from GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) by AS4PR08MB7601.eurprd08.prod.outlook.com (2603:10a6:20b:4ff::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7897.18; Sat, 24 Aug 2024 09:27:28 +0000 Received: from GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0]) by GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0%2]) with mapi id 15.20.7918.011; Sat, 24 Aug 2024 09:27:28 +0000 From: Mikhail Kshevetskiy To: Tom Rini , Joe Hershberger , Ramon Fried , Mattijs Korpershoek , Simon Glass , Heinrich Schuchardt , AKASHI Takahiro , Michal Simek , Francis Laniel , Anand Moon , Mikhail Kshevetskiy , Marek Vasut , Ilias Apalodimas , Masahisa Kojima , Sean Anderson , Baruch Siach , Yasuharu Shibata , u-boot@lists.denx.de Subject: [PATCH v5 02/11] net/tcp: fix selective acknowledge Date: Sat, 24 Aug 2024 12:27:07 +0300 Message-ID: <20240824092716.1042696-3-mikhail.kshevetskiy@iopsys.eu> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240824092716.1042696-1-mikhail.kshevetskiy@iopsys.eu> References: <20240824092716.1042696-1-mikhail.kshevetskiy@iopsys.eu> X-ClientProxiedBy: GV3P280CA0011.SWEP280.PROD.OUTLOOK.COM (2603:10a6:150:b::7) To GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: GV2PR08MB8121:EE_|AS4PR08MB7601:EE_ X-MS-Office365-Filtering-Correlation-Id: 36f62a81-e394-4bbb-0b43-08dcc41ef8cc X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|366016|376014|1800799024|52116014|7416014|921020|38350700014; X-Microsoft-Antispam-Message-Info: n27oCOaaaAzZRiXPRxXVENnEOyeZ7fzLnoOV05vzStvQK+cuOiQr1gFuEhYbBOWhb/Okx1SjdoE6/qa7X6gGb4ei95S754TOYBx/nO8NWdFSfqz5SaroI5hGK7JjLrdg816t5kJFq9jEdtkhAR0pTvrO7X+O/3pTjIgCpMPLLERriUP+SojLpmKCeSslchCRleYON6CSwTqzi3tKsO4xKdmyzQ+xc6z2C1IODkwTLKsHJ837YU+yhYlwp2zi1+DOL7rFXRLFvlboj7au3wkEokHNSy+x5FpTuWVGFCx59XgNNz5jrFsz/7kqgGL9PT7734HjOPw3cm/QQcz1eCkRmN/EgG0xMWchhCvnVQct1eVQt5pQNHX2ddMiirTTiNe6qLz5TxbYh/wDaFMyNouqd7zPfVSn1ePCmKsxexAm4l7aML1QQAgVU3AmtEXpsakhV7v1Yl5QSH2SMQMghHFmIljyMVIqZae1Zmg5Haco0KZhssDpSzpeuWVUY4bn6vQ01PwJO/jkCfnveLjswPj4ui6tN9MLoRI+hPGpBjqvVAowBdSrDVdNgi8RxVZvTUpaCHWOC2PimleqFmCw8UTjqHtj/N6wcKDHJkfX87pNFzJqZQTq4v8L06uuUZDRkEz5VBq3AXbIvHH1y2d8H3bjgynAyqVrNACgMmLBiUnpwxAE4njyftDx/WaeHegGccJ74Ik2XYCH5F45mFy+4to3K8RQPGVf5WCAZJcgkxPLj0iZEiB2Nc6Me7XZNCGudsqo8Mj+E1rXVCknkIuaSebQ2lD2WzMZHVkfG7/ftXDUKH4Gq1A0zpG5tBs0qRJzLd0edndjg4OjyYGGvj1YnL4CfIMQ9HfGvLfvcBHe/J3Ju53qO1+W3OskimkaYQDVxf1rPV6spfXYtMOYS4pU0PtoxGAizll46ZOwbW+6+frGKAAn+8KD1M8mbq6w6TC4R9KZwkmBa9NMsDBS+ObNcbMkeq+S+Mg4MVpdhYZpUwmIqHgyqRKS7QPinmJOCaBr/N0OE1YNtdtQig6ITeMXRrkCsgc67xBd9SyySYcly0IxGWRtDFsj9tfb+lMqLBbjLKi0U0weUw3sK7MSoiQtAPwV1XMF4Ewe1lEqb3F5bbsGLsnCCVWyGLrF3SjV604HgGZv1F/mb7h8O0PvWmJPYc7EFFz2scl3IDvOuk0u5jZSmrwcRxxz7W0VTIUwQ6rfMgGfGYjB2789hs7zUNgmPWVuXe5vWXboItc5OkhdgOmqhFiiydcZTUzPCFjPIJ/MOZJVlfwXj6/DXK595BG9y4cJZS0/Ka4umcnfUwJB4Y0RQfYzVNjqUFcNCnnzp7oZY/9+S2ideAxGyaMjNqJ2gG29F4lEmmRgaVOx8v3blcIsAdBdMEudG22HZTi3FBcP9tFbO1Yxw3i4EOt15vkXGlh4U52JyxZxc7EBoAqAZYEoubU= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:GV2PR08MB8121.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(366016)(376014)(1800799024)(52116014)(7416014)(921020)(38350700014); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: YLxk4z65DgJdAZFJdxhFzdD+fh8iulifdfUfZlPGLRFN2WSgASAB4MxokGasAMPy92ydJliLIjANCvmzCrNGOOiMDx1TV/MLIBeb+EWjl1OlWmS8Ql+GUfItDne05hJg/sb+0c6DIaZM2GhcVyP4xTCe7hBDrcSArJaHXxmvh8YuQ9Z3IEdB84ByqsxbRpC83Z8M6i01JMKxL3bLx9yOJKB82oHgjjQ1TVUwsU/5Hgu8naHMMavG5WCRFDrmR+Umpg/FLJv85bSdS0rBFq5aCQbqBseI4f9D046Yxrf0DMl889k9lo7RmGIQ/IcmV94zUGhbfH/wA1pD4Wg0ebOo59aMOArHW1WjXCQ4poJQa7xyf5XZqSCAo4410kfIybQEOH88iH4Dsv3TE54WwDIEviq6+ca2L/IDbnZKplmGE1RS03CgC//XnGzKSTRusCGOvHcMK69pWv3ACnxXROXzZrt26AwO8y/Es2a4JuZYGNs6ygPWhpUuGbBeF/W6h9K9AllaEmi7G0HHwvEaKlB0NeunotBxeKQv6hUynf334aZd9WbJALZmz4euoFo7Rn28JWHE53PLuPKucGWQ/JVTv/kAHP7l7qDar9k4YolwFh+qylScNC/TYPfhuqSudfC6WzxRoBxoahdzhJ7zOyP2FZkngVp+Z71LPExFCN81ysUdKDiNXH8p5lcQa2dsRIHIT3Pdh9XdQjjPxNYQ2lNjrdZSdbJQmvGWqAkhATt4/fNOhmTDkeYNHIW+/qmy5sIKpo2cKPW0qNb6f/BOwsAtxZaLyXnfawC0PvoV8CNenVVvfMGbeWaDme94Nqt9pC1yQHo6K0jkJjg4Hre0aYPjZJvRUalE+9m0BjonWSc5kmVnrPXD+M+i7fRXtS5NOVNfRXOlECpW4jsfr7ncux/aoucWJvxQnNYcsGULnWBBqXjmv4CVxUdvedpJK9qSq+1L4ugLR/K3njq2TaiExcJ0cES80A7dLzPJzzSaHSo1zlnkHy0STIzdtLUWhW3Ak/FxB9jJjv/8pJpMJ/kjfHNRIr3UzPFxFVJflE/t6VddLAjeh0lEiKC/vfOXdl5YTbLrXPk940QacQm1W+LbSJtOdTUayLQAydo7kICmCJWRbzTnN4TXFvouGiHCG12CLsjW9tw8km7IDjHWJ+GxhpGQfWlYD7T0RK0sWccyHB6mRbgE793AEPm6wLmSbnLdqdKxrWCbcRT+0QCi87rr6IUVnOpLHCS6mZkxWwK1O0jfxm2Qsgf+QcVZr86QLW2B0J8IHrI0WjgGMc+7L4KDxjU7uXkFeeEbdQClN4+HDILcJU1uOMwLSC4hsQSDz7LRf2tMIRE4GA8ua1DNgwLNvScF6kYZBS6CurecchhbvKQcn0JLoWcpiCnkD3cUlXqWifVtj9m3yNugGfo1+9nFNN8QvaFL7YRjgXleOVTwRA8xsW+9QQy0Red6uVAvAkFKZ8SRa/mEhy+myKTHdL73HppV2mFQPKQjiJX77sUTTIQmkeqirR34u9/Mep0ax3rqUEyKaphO2DcPc1auQ0OWassRKjSTnP2MAsRnYnagWfIVnqxkmNYUJmO3Mx5OX74/65vxklQmbUtL/7rKaN4SDJBOkDWIMmLUwAdHWCN4G+QkSy4= X-OriginatorOrg: iopsys.eu X-MS-Exchange-CrossTenant-Network-Message-Id: 36f62a81-e394-4bbb-0b43-08dcc41ef8cc X-MS-Exchange-CrossTenant-AuthSource: GV2PR08MB8121.eurprd08.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Aug 2024 09:27:28.3316 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 8d891be1-7bce-4216-9a99-bee9de02ba58 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: lvjhvk/leC9VaVr4koy/WOvyYdib8kGEURVSGRmlbYQszNzWlN+e1DfLUrIdGy0jI74/rZyixUabLOBR+P0sX3tkynAYJFIQTYQNm0FmUGw= X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS4PR08MB7601 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Current code assume that all (except last) packets are of the same size. This is definitely wrong. Replace SACK code with a new one, that does not rely on this assumption. Also this code uses less memory. Signed-off-by: Mikhail Kshevetskiy Reviewed-by: Simon Glass --- net/tcp.c | 200 +++++++++++++++++++++++------------------------------- 1 file changed, 86 insertions(+), 114 deletions(-) diff --git a/net/tcp.c b/net/tcp.c index 3e3118de450..724536cb352 100644 --- a/net/tcp.c +++ b/net/tcp.c @@ -38,21 +38,6 @@ static u32 tcp_ack_edge; static int tcp_activity_count; -/* - * Search for TCP_SACK and review the comments before the code section - * TCP_SACK is the number of packets at the front of the stream - */ - -enum pkt_state {PKT, NOPKT}; -struct sack_r { - struct sack_edges se; - enum pkt_state st; -}; - -static struct sack_r edge_a[TCP_SACK]; -static unsigned int sack_idx; -static unsigned int prev_len; - /* * TCP lengths are stored as a rounded up number of 32 bit words. * Add 3 to length round up, rounded, then divided into the @@ -69,6 +54,11 @@ static enum tcp_state current_tcp_state; /* Current TCP RX packet handler */ static rxhand_tcp *tcp_packet_handler; +static inline s32 tcp_seq_cmp(u32 a, u32 b) +{ + return (s32)(a - b); +} + /** * tcp_get_tcp_state() - get current TCP state * @@ -267,6 +257,7 @@ int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len, action = TCP_FIN; current_tcp_state = TCP_FIN_WAIT_1; } else { + tcp_lost.len = TCP_OPT_LEN_2; current_tcp_state = TCP_SYN_SENT; } break; @@ -353,6 +344,20 @@ int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len, return pkt_hdr_len; } +static void tcp_update_ack_edge(void) +{ + if (tcp_seq_cmp(tcp_ack_edge, tcp_lost.hill[0].l) >= 0) { + tcp_ack_edge = tcp_lost.hill[0].r; + + memmove(&tcp_lost.hill[0], &tcp_lost.hill[1], + (TCP_SACK_HILLS - 1) * sizeof(struct sack_edges)); + + tcp_lost.len -= TCP_OPT_LEN_8; + tcp_lost.hill[TCP_SACK_HILLS - 1].l = TCP_O_NOP; + tcp_lost.hill[TCP_SACK_HILLS - 1].r = TCP_O_NOP; + } +} + /** * tcp_hole() - Selective Acknowledgment (Essential for fast stream transfer) * @tcp_seq_num: TCP sequence start number @@ -360,106 +365,79 @@ int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len, */ void tcp_hole(u32 tcp_seq_num, u32 len) { - u32 idx_sack, sack_in; - u32 sack_end = TCP_SACK - 1; - u32 hill = 0; - enum pkt_state expect = PKT; - u32 seq = tcp_seq_num - tcp_seq_init; - u32 hol_l = tcp_ack_edge - tcp_seq_init; - u32 hol_r = 0; - - /* Place new seq number in correct place in receive array */ - if (prev_len == 0) - prev_len = len; - - idx_sack = sack_idx + ((tcp_seq_num - tcp_ack_edge) / prev_len); - if (idx_sack < TCP_SACK) { - edge_a[idx_sack].se.l = tcp_seq_num; - edge_a[idx_sack].se.r = tcp_seq_num + len; - edge_a[idx_sack].st = PKT; + int i, j, cnt, cnt_move; - /* - * The fin (last) packet is not the same length as data - * packets, and if it's length is recorded and used for - * array index calculation, calculation breaks. - */ - if (prev_len < len) - prev_len = len; - } + cnt = (tcp_lost.len - TCP_OPT_LEN_2) / TCP_OPT_LEN_8; + for (i = 0; i < cnt; i++) { + if (tcp_seq_cmp(tcp_lost.hill[i].r, tcp_seq_num) < 0) + continue; + if (tcp_seq_cmp(tcp_lost.hill[i].l, tcp_seq_num + len) > 0) + break; - debug_cond(DEBUG_DEV_PKT, - "TCP 1 seq %d, edg %d, len %d, sack_idx %d, sack_end %d\n", - seq, hol_l, len, sack_idx, sack_end); + if (tcp_seq_cmp(tcp_lost.hill[i].l, tcp_seq_num) > 0) + tcp_lost.hill[i].l = tcp_seq_num; + if (tcp_seq_cmp(tcp_lost.hill[i].l, tcp_seq_num) < 0) { + len += tcp_seq_num - tcp_lost.hill[i].l; + tcp_seq_num = tcp_lost.hill[i].l; + } + if (tcp_seq_cmp(tcp_lost.hill[i].r, tcp_seq_num + len) >= 0) { + tcp_update_ack_edge(); + return; + } - /* Right edge of contiguous stream, is the left edge of first hill */ - hol_l = tcp_seq_num - tcp_seq_init; - hol_r = hol_l + len; + /* check overlapping with next hills */ + cnt_move = 0; + tcp_lost.hill[i].r = tcp_seq_num + len; + for (j = i + 1; j < cnt; j++) { + if (tcp_seq_cmp(tcp_lost.hill[j].l, tcp_lost.hill[i].r) > 0) + break; - if (IS_ENABLED(CONFIG_PROT_TCP_SACK)) - tcp_lost.len = TCP_OPT_LEN_2; + tcp_lost.hill[i].r = tcp_lost.hill[j].r; + cnt_move++; + } - debug_cond(DEBUG_DEV_PKT, - "TCP 1 in %d, seq %d, pkt_l %d, pkt_r %d, sack_idx %d, sack_end %d\n", - idx_sack, seq, hol_l, hol_r, sack_idx, sack_end); - - for (sack_in = sack_idx; sack_in < sack_end && hill < TCP_SACK_HILLS; - sack_in++) { - switch (expect) { - case NOPKT: - switch (edge_a[sack_in].st) { - case NOPKT: - debug_cond(DEBUG_INT_STATE, "N"); - break; - case PKT: - debug_cond(DEBUG_INT_STATE, "n"); - if (IS_ENABLED(CONFIG_PROT_TCP_SACK)) { - tcp_lost.hill[hill].l = - edge_a[sack_in].se.l; - tcp_lost.hill[hill].r = - edge_a[sack_in].se.r; - } - expect = PKT; - break; - } - break; - case PKT: - switch (edge_a[sack_in].st) { - case NOPKT: - debug_cond(DEBUG_INT_STATE, "p"); - if (sack_in > sack_idx && - hill < TCP_SACK_HILLS) { - hill++; - if (IS_ENABLED(CONFIG_PROT_TCP_SACK)) - tcp_lost.len += TCP_OPT_LEN_8; - } - expect = NOPKT; - break; - case PKT: - debug_cond(DEBUG_INT_STATE, "P"); - - if (tcp_ack_edge == edge_a[sack_in].se.l) { - tcp_ack_edge = edge_a[sack_in].se.r; - edge_a[sack_in].st = NOPKT; - sack_idx++; - } else { - if (IS_ENABLED(CONFIG_PROT_TCP_SACK) && - hill < TCP_SACK_HILLS) - tcp_lost.hill[hill].r = - edge_a[sack_in].se.r; - if (IS_ENABLED(CONFIG_PROT_TCP_SACK) && - sack_in == sack_end - 1) - tcp_lost.hill[hill].r = - edge_a[sack_in].se.r; - } - break; + if (cnt_move > 0) { + if (cnt > i + cnt_move + 1) + memmove(&tcp_lost.hill[i + 1], + &tcp_lost.hill[i + cnt_move + 1], + cnt_move * sizeof(struct sack_edges)); + + cnt -= cnt_move; + tcp_lost.len = TCP_OPT_LEN_2 + cnt * TCP_OPT_LEN_8; + for (j = cnt; j < TCP_SACK_HILLS; j++) { + tcp_lost.hill[j].l = TCP_O_NOP; + tcp_lost.hill[j].r = TCP_O_NOP; } - break; } + + tcp_update_ack_edge(); + return; } - debug_cond(DEBUG_INT_STATE, "\n"); - if (!IS_ENABLED(CONFIG_PROT_TCP_SACK) || tcp_lost.len <= TCP_OPT_LEN_2) - sack_idx = 0; -} + + if (i == TCP_SACK_HILLS) { + tcp_update_ack_edge(); + return; + } + + if (cnt < TCP_SACK_HILLS) { + cnt_move = cnt - i; + cnt++; + } else { + cnt = TCP_SACK_HILLS; + cnt_move = TCP_SACK_HILLS - i; + } + + if (cnt_move > 0) + memmove(&tcp_lost.hill[i + 1], + &tcp_lost.hill[i], + cnt_move * sizeof(struct sack_edges)); + + tcp_lost.hill[i].l = tcp_seq_num; + tcp_lost.hill[i].r = tcp_seq_num + len; + tcp_lost.len = TCP_OPT_LEN_2 + cnt * TCP_OPT_LEN_8; + + tcp_update_ack_edge(); +}; /** * tcp_parse_options() - parsing TCP options @@ -509,7 +487,6 @@ static u8 tcp_state_machine(u8 tcp_flags, u32 tcp_seq_num, int payload_len) u8 tcp_push = tcp_flags & TCP_PUSH; u8 tcp_ack = tcp_flags & TCP_ACK; u8 action = TCP_DATA; - int i; /* * tcp_flags are examined to determine TX action in a given state @@ -536,6 +513,7 @@ static u8 tcp_state_machine(u8 tcp_flags, u32 tcp_seq_num, int payload_len) action = TCP_SYN | TCP_ACK; tcp_seq_init = tcp_seq_num; tcp_ack_edge = tcp_seq_num + 1; + tcp_lost.len = TCP_OPT_LEN_2; current_tcp_state = TCP_SYN_RECEIVED; } else if (tcp_ack || tcp_fin) { action = TCP_DATA; @@ -552,13 +530,7 @@ static u8 tcp_state_machine(u8 tcp_flags, u32 tcp_seq_num, int payload_len) action |= TCP_ACK; tcp_seq_init = tcp_seq_num; tcp_ack_edge = tcp_seq_num + 1; - sack_idx = 0; - edge_a[sack_idx].se.l = tcp_ack_edge; - edge_a[sack_idx].se.r = tcp_ack_edge; - prev_len = 0; current_tcp_state = TCP_ESTABLISHED; - for (i = 0; i < TCP_SACK; i++) - edge_a[i].st = NOPKT; if (tcp_syn && tcp_ack) action |= TCP_PUSH; From patchwork Sat Aug 24 09:27:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Kshevetskiy X-Patchwork-Id: 1976360 X-Patchwork-Delegate: pbrobinson@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.a=rsa-sha256 header.s=selector2 header.b=ZBKBbh50; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (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 4WrWng2MwSz1yXd for ; Sat, 24 Aug 2024 19:28:07 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id D052E88C8B; Sat, 24 Aug 2024 11:27:36 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.b="ZBKBbh50"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 187E688B36; Sat, 24 Aug 2024 11:27:34 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,SPF_HELO_PASS, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 Received: from EUR05-AM6-obe.outbound.protection.outlook.com (mail-am6eur05on20719.outbound.protection.outlook.com [IPv6:2a01:111:f403:2612::719]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 4122888B69 for ; Sat, 24 Aug 2024 11:27:31 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mikhail.kshevetskiy@genexis.eu ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=J+b6fsoBJXni2BIhclKLnjt+ULhRkxMO+ucYax0yZdbJ9gTDlxK8XNkkWRVnccBnklfA5HRA3lkIri0E+Gct0RGV4lx71sJYIBWo4CJUI4gifDBT0Sxo9aYrWNZY8OsKe8cgCaiYf45H6ORCqPLKliuKACY6Ult5tHNTdnK0N8PWeHaVrKubJ0IwhdBWM3iEDacfqWwENkFOGsJoaWkDZ9LXlrnJeDtPbSi0F03KR+E/F7C7KltcH17iDrgygDmYDtJrVc0X/a89+hFFAdPrpXlR48t7fuRIaWQ8B4f02wdF0qkaTa9ATox8tLdnCgr3xieMrItgFMC8/tlAFmEA0A== 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=+2S0JGgngRg3t88tBV2E65cdwVGw5CdjN8FATQn64pg=; b=eYTtBkkjupY5Kb5xXH5bzw0NxBG9ZwjaV8qflshiQFk6duSFz/LDeqxJ76GZq6D1x894opm74AbTpoHgL4YxdcGWa/IGnUStWoJwzUWUUU6pOX45GyBOuDDabn99bRtD+fNbh1m+wtM4/2ErbpB4+8s2m2WxN3GPi5AFXwD6OutdU1W9qAQBiR06XGsOwvc9TwWaE3wE5peV7F37bWcGI5LZpeayStsEdcOHPeq+QSUVytb5s51IFuLkl4eDhJCa/m+HVqTxbztPdn9LzbhOLCv3QlWmjDxNIr7Rq86Xtb2LJEyvdNNWwEho8TQ+N2uwKY1DL2J6Jf2p28DobKneCQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=genexis.eu; dmarc=pass action=none header.from=iopsys.eu; dkim=pass header.d=iopsys.eu; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iopsys.eu; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=+2S0JGgngRg3t88tBV2E65cdwVGw5CdjN8FATQn64pg=; b=ZBKBbh50YXdXIIl7wDh02p++8HC7N+ItnlVYSaxC35y1qLZ0Kr6Eo60LqBjewjIfK839OQWwY0QFNMyXAqgzrKKr3Z6tl7l8ewkageSJ8WCzN5aB2oU2KJMNCQvDb5CHFzQLOCHMtbU36W7IS6rye+w7WBsjCmwvGjYzQ9Q9lzReL21j01lYsUXiXoR9w3RfsfknwkzOVlfa+9KGggxbA1gEPIY9PzrnvNhlB9wMfLBQczwFWQFgogmidRQoF9V7PLAjvFbOMnAqlCFvjazjlFzbp7LXA+bV0CYwBSFqARCj2B7a952xAihAcMTGZbkQVyTk/zBJjbP0rq8/XFu67Q== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=iopsys.eu; Received: from GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) by AS4PR08MB7601.eurprd08.prod.outlook.com (2603:10a6:20b:4ff::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7897.18; Sat, 24 Aug 2024 09:27:29 +0000 Received: from GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0]) by GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0%2]) with mapi id 15.20.7918.011; Sat, 24 Aug 2024 09:27:29 +0000 From: Mikhail Kshevetskiy To: Tom Rini , Joe Hershberger , Ramon Fried , Mattijs Korpershoek , Simon Glass , Heinrich Schuchardt , AKASHI Takahiro , Michal Simek , Francis Laniel , Anand Moon , Mikhail Kshevetskiy , Marek Vasut , Ilias Apalodimas , Masahisa Kojima , Sean Anderson , Baruch Siach , Yasuharu Shibata , u-boot@lists.denx.de Subject: [PATCH v5 03/11] net/tcp: put connection specific data into a tcp_stream structure Date: Sat, 24 Aug 2024 12:27:08 +0300 Message-ID: <20240824092716.1042696-4-mikhail.kshevetskiy@iopsys.eu> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240824092716.1042696-1-mikhail.kshevetskiy@iopsys.eu> References: <20240824092716.1042696-1-mikhail.kshevetskiy@iopsys.eu> X-ClientProxiedBy: GV3P280CA0011.SWEP280.PROD.OUTLOOK.COM (2603:10a6:150:b::7) To GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: GV2PR08MB8121:EE_|AS4PR08MB7601:EE_ X-MS-Office365-Filtering-Correlation-Id: ec636eb8-22f8-43f7-0cb0-08dcc41ef98b X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|366016|376014|1800799024|52116014|7416014|921020|38350700014; X-Microsoft-Antispam-Message-Info: RMFKcQUGeM5sVZXW1jntpL++5eWX9RR/bTLrYl7ReBPuuASsonlr3DLOHujZ4TRH8HP489TPRHsDEMlYOM/v19+fsyZWvx9SwzuU5v7dhfQljBeLAFKKMPtDm3iLgUfLED4orxZFtfpbqB8JSC9/styL2NRKEO+NCJJ+rcgwPO7vpQeVenmfjfDlmFFxkiZXRu70G/Zpc6SO5wRB6m6jl2sCoKfMOj1HxTN6p4kSYPL9A+K3INyeO++b6Os30cFIxvB4gymNcnyrJKjF8c9HUEJa6P10kkDOfhq5/tOz5ffT+dhxy98gN8hhE1UczmdOhCEje0MKRNs1Zc6JHL3QQL2fnIXpX6g9PYo/AFmwU9Fa76OuJqnMU8FG5hRXfMK/8EooDddDGAtSotZGkGOl66zaKorX1X6e1UE3gwYm6KS7W9kSxmnWE69xEtqMpPXyvbA0yGC5lpXnDpjwbT8eRE9ZLHV4XN4W3KkjRVQTRR37XF0/KpyhxztHnt4eY6TX5Fap+UME7uqpBIOR7oukkhp9rVB1+6cUqd9hlAlrJwTim2bK2POJz5CCCzKRTXNt8A176bfrHcz4G1vtmRF0RbtXSZfjATnnxVOxLgziPy/+7ZiW7rb0MsmfbW+5UpvTQf5tnqgB3fWxoneCZX98S9nLK2y654sjJuAnxAWqg5DMuykMMVYVmRo//QGk3KD6VQkpnqvbmWh1EWb3M/+y6s10UXPMjHF97hAzfUdtoAn4M2zDXE83WMuRI449VEYqyOo4wif167Mo+4dt8k3JD1c4RXUIfl00TjUoKCD6uy86zxKD2xQXku70J00VvEPZI4sf5pjZYZdeu5TvmJgKHkiZ5CjfM+Wwg8ufJ5M4OA4MIS+UjJebX6O7LfAjCR/wrOqk9CcMb+Zjfu2cScWSK8kIL3WFTXty4hahQPuo8n5orUPpLHihTiEtoJbxP5zn4Ogp9JiJRtSB7Cwnz5mJEM6J8Da1LDiwyXfOnebCwxo9hUQ6UKG8IV1aBebfHd0SfJGeShdpfs4OIzEsJ8PvNEE5cb6a+B2d7ncyp2ZJk15Fxtwzc9mwr3IrWn1zM1bcrh8SL+QY6HK7/KykFXpkgmyepWM+PCddL0YUPo0YeQy8Sy0AzBlhgKWjkiuvREwNH2FJMrNCuYQNQNL1UzoR99pYiuq2cYYBFRoYGUrnVE65PVP5JLecRJjsL3KUAtPvgrHJu/bw8aYDbHuxl80mPcfT9CltqWe/5cMK3r46DD2l+umBwpLj4JKNYHeG+Dojzoi3a4THIgoCmhcM59eka5YR8533wsh7p8g8sF8LEkRuqeCjJu9TbYXFjYc1iaA3uVvOF2/U5LpJWP4Wddkh3Ih0NeVeeKLHQRZmapcODvZqQuvCVaLF4HVQxDxQhYKkkDjYpAqvxq490yeBbmjr7XBaQPsWGITo+7C1NXTYwPs= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:GV2PR08MB8121.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(366016)(376014)(1800799024)(52116014)(7416014)(921020)(38350700014); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: ifRoDlHFsJt7p6ZO7NTT3cbpTJ0XYFtopDoPvKOG7mZsvp5wcsat0XQDIh2CI/W8ge5jU9ZbWV+ciAzj77K32Q9tDlav7P/9GvKhCoTgaIF+Gjf4UAeQxbqRzJPVpk620MgfTl8QPuQZZsJc4NKpI/eN/q12zk0JsxYTzgh1bBDqoKl5JeUAPnfZoo9eiU9w9SwG8oHUp1U+RL9Z0ggR8FMEDRJQnsgz2aHj74MPH7/FP11rtW6AT/tDW+iCYFMXx869ZcSak7C/KDn864vc/VuvRJtTqxRSg7OeHh7F8Ni16BUwj9rY2+sAlgVD//u9dskq9DhMI5LDwY1VCRhGD3l6XgZ9XM0A8OzlL+jRpT4Y4QCJU/BNm0NSg8VFbTIUvbtHQRg9sObQ7eGNSkhjwBNb6uAxw3TXTucwBdShDLvswCC/fFVE04m5fkyx7Ljq4OablPV9fdKp+KGlLKYTO2Q9yKuUTxep2Ri/ChBA5vCZiLAwBvWs2s2wv8sq6sSwJ7zpvPeB68q+55FjgeZc2nE9eptWCHxrvuITmaS2Irfpr9shqODZmbkBQR8j/FGfFIbFoNaX/FLphKnFT7eGoL9/EAXB2JoqkfM2ojzIZSFFh9Vo+eIy2CdNsw+HHZJ5SU/elCux0w0qTx2ImDcJIQK6LeX+/2IyCjV1jcEauXWjQQmZOzDk9znbH2EgQxFlUO0HVHDRnWbK4j2Ms7htqrUmOipI20VRuCtvlkqZgoqMJZb8ML6NKbrxKccoY5OZ7GGl1a1Z9HOVi6I2H/zMP9py/z9Lsgd376VpPXqUVZx7ZPOWPTzQ5RnO7J/rCa4b3U9sHgHlP8/JJ2/USgieiLQxaJNv91NwThiIq3UXEiAXIExdy0n3CRQp0SRKdkkFes2gc4Xh6H5nnfEPdc16h/irTE7huNX//ZyHuuvP4ZKWfYgzUK3XETYi8geP4D/19+qQ0YDLgVBGloqnvh+kYOjuf4V2M5sT2t/deg5yQK1rtFjqQtT321MarqGXjAcM90T8MkA48dkH63RwfY1vzTcuVbGQkgspyPYHXtZ8DUnK6hXZC44129IgDdUmy+39WYAZUeZNfT/EVAn3S5Z2fEAC33ps0lT18yYp0b+Ct/IoVeX1LQ0V4tVH0NeutIDw2IjHeNq/tbIbfR7X0OzJHUOM9Sh5P1YYCmqPrg8c2ab2WFpzG30S6nHG+XswWUgn0Et+0sD8yyY25gkqHN2g+Id7ZukAqrgLq10cF0/2ubXwRSWJTerGpuvte6mOt6ZvUJhNS6mOAvPbsfNUS7G+etFgnFP8dyXPXtrNk4ngok1gFHDE8tneii0N5fv1Edt3c9E5SRurf2damN4qLSvBZf2qtgHX9UkHqrNyELBJ/FbgVdJZnYtpNWjeHYPotmQXENvCmTfVBUC2ba4uDIz+VT4zYWA48WogBzJcK36OiNa3FrHHHetOYbz3pXFFbpKR0vlfjrAj2ME92Xn0ssp0fQ8fU5oo3XxfGxKYuYpbbM1GwnDc95r2RukqZWC2qInWpT3KysjPg6b9kzWzlc6JufFQs3Smn9F52xBOR8CYbFuP7nyByTd2YdCfy/ik3x8ObvlyumXh65RZxKbuLvSVcjEjU23BD4I+VrqcP0/0VIE= X-OriginatorOrg: iopsys.eu X-MS-Exchange-CrossTenant-Network-Message-Id: ec636eb8-22f8-43f7-0cb0-08dcc41ef98b X-MS-Exchange-CrossTenant-AuthSource: GV2PR08MB8121.eurprd08.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Aug 2024 09:27:29.6469 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 8d891be1-7bce-4216-9a99-bee9de02ba58 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: KzDFqcMZkXcH4jKNH7GjelP9g5jYcQfUwzLGT4BRct8CuyO10F1gnHhE/gcKrFzpfxTYGa754TSPxMSQ5qTj5ZXUj5Q00WSjLlUy8ql3hIc= X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS4PR08MB7601 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean no functional changes Signed-off-by: Mikhail Kshevetskiy Reviewed-by: Simon Glass --- include/net/tcp.h | 37 +++++++- net/net.c | 11 ++- net/tcp.c | 231 +++++++++++++++++++++++----------------------- net/wget.c | 3 +- 4 files changed, 163 insertions(+), 119 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index c29d4ce24a7..14aee64cb1c 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -277,9 +277,40 @@ enum tcp_state { TCP_FIN_WAIT_2 }; -enum tcp_state tcp_get_tcp_state(void); -void tcp_set_tcp_state(enum tcp_state new_state); -int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len, +/** + * struct tcp_stream - TCP data stream structure + * + * @state: TCP connection state + * + * @seq_init: Initial receive sequence number + * @ack_edge: Receive next + * + * @loc_timestamp: Local timestamp + * @rmt_timestamp: Remote timestamp + * + * @lost: Used for SACK + */ +struct tcp_stream { + /* TCP connection state */ + enum tcp_state state; + + u32 seq_init; + u32 ack_edge; + + /* TCP option timestamp */ + u32 loc_timestamp; + u32 rmt_timestamp; + + /* TCP sliding window control used to request re-TX */ + struct tcp_sack_v lost; +}; + +struct tcp_stream *tcp_stream_get(void); + +enum tcp_state tcp_get_tcp_state(struct tcp_stream *tcp); +void tcp_set_tcp_state(struct tcp_stream *tcp, enum tcp_state new_state); +int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int dport, + int sport, int payload_len, u8 action, u32 tcp_seq_num, u32 tcp_ack_num); /** diff --git a/net/net.c b/net/net.c index d9bc9df643f..6c5ee7e0925 100644 --- a/net/net.c +++ b/net/net.c @@ -414,7 +414,7 @@ int net_init(void) /* Only need to setup buffer pointers once. */ first_call = 0; if (IS_ENABLED(CONFIG_PROT_TCP)) - tcp_set_tcp_state(TCP_CLOSED); + tcp_set_tcp_state(tcp_stream_get(), TCP_CLOSED); } return net_init_loop(); @@ -915,6 +915,9 @@ int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport, uchar *pkt; int eth_hdr_size; int pkt_hdr_size; +#if defined(CONFIG_PROT_TCP) + struct tcp_stream *tcp; +#endif /* make sure the net_tx_packet is initialized (net_init() was called) */ assert(net_tx_packet != NULL); @@ -941,8 +944,12 @@ int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport, break; #if defined(CONFIG_PROT_TCP) case IPPROTO_TCP: + tcp = tcp_stream_get(); + if (tcp == NULL) + return -EINVAL; + pkt_hdr_size = eth_hdr_size - + tcp_set_tcp_header(pkt + eth_hdr_size, dport, sport, + + tcp_set_tcp_header(tcp, pkt + eth_hdr_size, dport, sport, payload_len, action, tcp_seq_num, tcp_ack_num); break; diff --git a/net/tcp.c b/net/tcp.c index 724536cb352..6646f171b83 100644 --- a/net/tcp.c +++ b/net/tcp.c @@ -24,19 +24,8 @@ #include #include -/* - * TCP sliding window control used by us to request re-TX - */ -static struct tcp_sack_v tcp_lost; - -/* TCP option timestamp */ -static u32 loc_timestamp; -static u32 rmt_timestamp; - -static u32 tcp_seq_init; -static u32 tcp_ack_edge; - static int tcp_activity_count; +static struct tcp_stream tcp_stream; /* * TCP lengths are stored as a rounded up number of 32 bit words. @@ -48,9 +37,6 @@ static int tcp_activity_count; #define SHIFT_TO_TCPHDRLEN_FIELD(x) ((x) << 4) #define GET_TCP_HDR_LEN_IN_BYTES(x) ((x) >> 2) -/* TCP connection state */ -static enum tcp_state current_tcp_state; - /* Current TCP RX packet handler */ static rxhand_tcp *tcp_packet_handler; @@ -60,22 +46,30 @@ static inline s32 tcp_seq_cmp(u32 a, u32 b) } /** - * tcp_get_tcp_state() - get current TCP state + * tcp_get_tcp_state() - get TCP stream state + * @tcp: tcp stream * - * Return: Current TCP state + * Return: TCP stream state */ -enum tcp_state tcp_get_tcp_state(void) +enum tcp_state tcp_get_tcp_state(struct tcp_stream *tcp) { - return current_tcp_state; + return tcp->state; } /** - * tcp_set_tcp_state() - set current TCP state + * tcp_set_tcp_state() - set TCP stream state + * @tcp: tcp stream * @new_state: new TCP state */ -void tcp_set_tcp_state(enum tcp_state new_state) +void tcp_set_tcp_state(struct tcp_stream *tcp, + enum tcp_state new_state) { - current_tcp_state = new_state; + tcp->state = new_state; +} + +struct tcp_stream *tcp_stream_get(void) +{ + return &tcp_stream; } static void dummy_handler(uchar *pkt, u16 dport, @@ -138,29 +132,30 @@ u16 tcp_set_pseudo_header(uchar *pkt, struct in_addr src, struct in_addr dest, /** * net_set_ack_options() - set TCP options in acknowledge packets + * @tcp: tcp stream * @b: the packet * * Return: TCP header length */ -int net_set_ack_options(union tcp_build_pkt *b) +int net_set_ack_options(struct tcp_stream *tcp, union tcp_build_pkt *b) { b->sack.hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(LEN_B_TO_DW(TCP_HDR_SIZE)); b->sack.t_opt.kind = TCP_O_TS; b->sack.t_opt.len = TCP_OPT_LEN_A; - b->sack.t_opt.t_snd = htons(loc_timestamp); - b->sack.t_opt.t_rcv = rmt_timestamp; + b->sack.t_opt.t_snd = htons(tcp->loc_timestamp); + b->sack.t_opt.t_rcv = tcp->rmt_timestamp; b->sack.sack_v.kind = TCP_1_NOP; b->sack.sack_v.len = 0; if (IS_ENABLED(CONFIG_PROT_TCP_SACK)) { - if (tcp_lost.len > TCP_OPT_LEN_2) { + if (tcp->lost.len > TCP_OPT_LEN_2) { debug_cond(DEBUG_DEV_PKT, "TCP ack opt lost.len %x\n", - tcp_lost.len); - b->sack.sack_v.len = tcp_lost.len; + tcp->lost.len); + b->sack.sack_v.len = tcp->lost.len; b->sack.sack_v.kind = TCP_V_SACK; - b->sack.sack_v.hill[0].l = htonl(tcp_lost.hill[0].l); - b->sack.sack_v.hill[0].r = htonl(tcp_lost.hill[0].r); + b->sack.sack_v.hill[0].l = htonl(tcp->lost.hill[0].l); + b->sack.sack_v.hill[0].r = htonl(tcp->lost.hill[0].r); /* * These SACK structures are initialized with NOPs to @@ -168,17 +163,17 @@ int net_set_ack_options(union tcp_build_pkt *b) * SACK structures used for both header padding and * internally. */ - b->sack.sack_v.hill[1].l = htonl(tcp_lost.hill[1].l); - b->sack.sack_v.hill[1].r = htonl(tcp_lost.hill[1].r); - b->sack.sack_v.hill[2].l = htonl(tcp_lost.hill[2].l); - b->sack.sack_v.hill[2].r = htonl(tcp_lost.hill[2].r); + b->sack.sack_v.hill[1].l = htonl(tcp->lost.hill[1].l); + b->sack.sack_v.hill[1].r = htonl(tcp->lost.hill[1].r); + b->sack.sack_v.hill[2].l = htonl(tcp->lost.hill[2].l); + b->sack.sack_v.hill[2].r = htonl(tcp->lost.hill[2].r); b->sack.sack_v.hill[3].l = TCP_O_NOP; b->sack.sack_v.hill[3].r = TCP_O_NOP; } b->sack.hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(ROUND_TCPHDR_LEN(TCP_HDR_SIZE + TCP_TSOPT_SIZE + - tcp_lost.len)); + tcp->lost.len)); } else { b->sack.sack_v.kind = 0; b->sack.hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(ROUND_TCPHDR_LEN(TCP_HDR_SIZE + @@ -194,13 +189,14 @@ int net_set_ack_options(union tcp_build_pkt *b) } /** - * net_set_ack_options() - set TCP options in SYN packets + * net_set_syn_options() - set TCP options in SYN packets + * @tcp: tcp stream * @b: the packet */ -void net_set_syn_options(union tcp_build_pkt *b) +void net_set_syn_options(struct tcp_stream *tcp, union tcp_build_pkt *b) { if (IS_ENABLED(CONFIG_PROT_TCP_SACK)) - tcp_lost.len = 0; + tcp->lost.len = 0; b->ip.hdr.tcp_hlen = 0xa0; @@ -219,14 +215,15 @@ void net_set_syn_options(union tcp_build_pkt *b) } b->ip.t_opt.kind = TCP_O_TS; b->ip.t_opt.len = TCP_OPT_LEN_A; - loc_timestamp = get_ticks(); - rmt_timestamp = 0; + tcp->loc_timestamp = get_ticks(); + tcp->rmt_timestamp = 0; b->ip.t_opt.t_snd = 0; b->ip.t_opt.t_rcv = 0; b->ip.end = TCP_O_END; } -int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len, +int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int dport, + int sport, int payload_len, u8 action, u32 tcp_seq_num, u32 tcp_ack_num) { union tcp_build_pkt *b = (union tcp_build_pkt *)pkt; @@ -249,21 +246,21 @@ int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len, &net_server_ip, &net_ip, tcp_seq_num, tcp_ack_num); tcp_activity_count = 0; - net_set_syn_options(b); + net_set_syn_options(tcp, b); tcp_seq_num = 0; tcp_ack_num = 0; pkt_hdr_len = IP_TCP_O_SIZE; - if (current_tcp_state == TCP_SYN_SENT) { /* Too many SYNs */ + if (tcp->state == TCP_SYN_SENT) { /* Too many SYNs */ action = TCP_FIN; - current_tcp_state = TCP_FIN_WAIT_1; + tcp->state = TCP_FIN_WAIT_1; } else { - tcp_lost.len = TCP_OPT_LEN_2; - current_tcp_state = TCP_SYN_SENT; + tcp->lost.len = TCP_OPT_LEN_2; + tcp->state = TCP_SYN_SENT; } break; case TCP_SYN | TCP_ACK: case TCP_ACK: - pkt_hdr_len = IP_HDR_SIZE + net_set_ack_options(b); + pkt_hdr_len = IP_HDR_SIZE + net_set_ack_options(tcp, b); b->ip.hdr.tcp_flags = action; debug_cond(DEBUG_DEV_PKT, "TCP Hdr:ACK (%pI4, %pI4, s=%u, a=%u, A=%x)\n", @@ -276,20 +273,20 @@ int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len, &net_server_ip, &net_ip, tcp_seq_num, tcp_ack_num); payload_len = 0; pkt_hdr_len = IP_TCP_HDR_SIZE; - current_tcp_state = TCP_FIN_WAIT_1; + tcp->state = TCP_FIN_WAIT_1; break; case TCP_RST | TCP_ACK: case TCP_RST: debug_cond(DEBUG_DEV_PKT, "TCP Hdr:RST (%pI4, %pI4, s=%u, a=%u)\n", &net_server_ip, &net_ip, tcp_seq_num, tcp_ack_num); - current_tcp_state = TCP_CLOSED; + tcp->state = TCP_CLOSED; break; /* Notify connection closing */ case (TCP_FIN | TCP_ACK): case (TCP_FIN | TCP_ACK | TCP_PUSH): - if (current_tcp_state == TCP_CLOSE_WAIT) - current_tcp_state = TCP_CLOSING; + if (tcp->state == TCP_CLOSE_WAIT) + tcp->state = TCP_CLOSING; debug_cond(DEBUG_DEV_PKT, "TCP Hdr:FIN ACK PSH(%pI4, %pI4, s=%u, a=%u, A=%x)\n", @@ -297,7 +294,7 @@ int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len, tcp_seq_num, tcp_ack_num, action); fallthrough; default: - pkt_hdr_len = IP_HDR_SIZE + net_set_ack_options(b); + pkt_hdr_len = IP_HDR_SIZE + net_set_ack_options(tcp, b); b->ip.hdr.tcp_flags = action | TCP_PUSH | TCP_ACK; debug_cond(DEBUG_DEV_PKT, "TCP Hdr:dft (%pI4, %pI4, s=%u, a=%u, A=%x)\n", @@ -308,9 +305,9 @@ int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len, pkt_len = pkt_hdr_len + payload_len; tcp_len = pkt_len - IP_HDR_SIZE; - tcp_ack_edge = tcp_ack_num; + tcp->ack_edge = tcp_ack_num; /* TCP Header */ - b->ip.hdr.tcp_ack = htonl(tcp_ack_edge); + b->ip.hdr.tcp_ack = htonl(tcp->ack_edge); b->ip.hdr.tcp_src = htons(sport); b->ip.hdr.tcp_dst = htons(dport); b->ip.hdr.tcp_seq = htonl(tcp_seq_num); @@ -344,78 +341,79 @@ int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len, return pkt_hdr_len; } -static void tcp_update_ack_edge(void) +static void tcp_update_ack_edge(struct tcp_stream *tcp) { - if (tcp_seq_cmp(tcp_ack_edge, tcp_lost.hill[0].l) >= 0) { - tcp_ack_edge = tcp_lost.hill[0].r; + if (tcp_seq_cmp(tcp->ack_edge, tcp->lost.hill[0].l) >= 0) { + tcp->ack_edge = tcp->lost.hill[0].r; - memmove(&tcp_lost.hill[0], &tcp_lost.hill[1], + memmove(&tcp->lost.hill[0], &tcp->lost.hill[1], (TCP_SACK_HILLS - 1) * sizeof(struct sack_edges)); - tcp_lost.len -= TCP_OPT_LEN_8; - tcp_lost.hill[TCP_SACK_HILLS - 1].l = TCP_O_NOP; - tcp_lost.hill[TCP_SACK_HILLS - 1].r = TCP_O_NOP; + tcp->lost.len -= TCP_OPT_LEN_8; + tcp->lost.hill[TCP_SACK_HILLS - 1].l = TCP_O_NOP; + tcp->lost.hill[TCP_SACK_HILLS - 1].r = TCP_O_NOP; } } /** * tcp_hole() - Selective Acknowledgment (Essential for fast stream transfer) + * @tcp: tcp stream * @tcp_seq_num: TCP sequence start number * @len: the length of sequence numbers */ -void tcp_hole(u32 tcp_seq_num, u32 len) +void tcp_hole(struct tcp_stream *tcp, u32 tcp_seq_num, u32 len) { int i, j, cnt, cnt_move; - cnt = (tcp_lost.len - TCP_OPT_LEN_2) / TCP_OPT_LEN_8; + cnt = (tcp->lost.len - TCP_OPT_LEN_2) / TCP_OPT_LEN_8; for (i = 0; i < cnt; i++) { - if (tcp_seq_cmp(tcp_lost.hill[i].r, tcp_seq_num) < 0) + if (tcp_seq_cmp(tcp->lost.hill[i].r, tcp_seq_num) < 0) continue; - if (tcp_seq_cmp(tcp_lost.hill[i].l, tcp_seq_num + len) > 0) + if (tcp_seq_cmp(tcp->lost.hill[i].l, tcp_seq_num + len) > 0) break; - if (tcp_seq_cmp(tcp_lost.hill[i].l, tcp_seq_num) > 0) - tcp_lost.hill[i].l = tcp_seq_num; - if (tcp_seq_cmp(tcp_lost.hill[i].l, tcp_seq_num) < 0) { - len += tcp_seq_num - tcp_lost.hill[i].l; - tcp_seq_num = tcp_lost.hill[i].l; + if (tcp_seq_cmp(tcp->lost.hill[i].l, tcp_seq_num) > 0) + tcp->lost.hill[i].l = tcp_seq_num; + if (tcp_seq_cmp(tcp->lost.hill[i].l, tcp_seq_num) < 0) { + len += tcp_seq_num - tcp->lost.hill[i].l; + tcp_seq_num = tcp->lost.hill[i].l; } - if (tcp_seq_cmp(tcp_lost.hill[i].r, tcp_seq_num + len) >= 0) { - tcp_update_ack_edge(); + if (tcp_seq_cmp(tcp->lost.hill[i].r, tcp_seq_num + len) >= 0) { + tcp_update_ack_edge(tcp); return; } /* check overlapping with next hills */ cnt_move = 0; - tcp_lost.hill[i].r = tcp_seq_num + len; + tcp->lost.hill[i].r = tcp_seq_num + len; for (j = i + 1; j < cnt; j++) { - if (tcp_seq_cmp(tcp_lost.hill[j].l, tcp_lost.hill[i].r) > 0) + if (tcp_seq_cmp(tcp->lost.hill[j].l, tcp->lost.hill[i].r) > 0) break; - tcp_lost.hill[i].r = tcp_lost.hill[j].r; + tcp->lost.hill[i].r = tcp->lost.hill[j].r; cnt_move++; } if (cnt_move > 0) { if (cnt > i + cnt_move + 1) - memmove(&tcp_lost.hill[i + 1], - &tcp_lost.hill[i + cnt_move + 1], + memmove(&tcp->lost.hill[i + 1], + &tcp->lost.hill[i + cnt_move + 1], cnt_move * sizeof(struct sack_edges)); cnt -= cnt_move; - tcp_lost.len = TCP_OPT_LEN_2 + cnt * TCP_OPT_LEN_8; + tcp->lost.len = TCP_OPT_LEN_2 + cnt * TCP_OPT_LEN_8; for (j = cnt; j < TCP_SACK_HILLS; j++) { - tcp_lost.hill[j].l = TCP_O_NOP; - tcp_lost.hill[j].r = TCP_O_NOP; + tcp->lost.hill[j].l = TCP_O_NOP; + tcp->lost.hill[j].r = TCP_O_NOP; } } - tcp_update_ack_edge(); + tcp_update_ack_edge(tcp); return; } if (i == TCP_SACK_HILLS) { - tcp_update_ack_edge(); + tcp_update_ack_edge(tcp); return; } @@ -428,23 +426,24 @@ void tcp_hole(u32 tcp_seq_num, u32 len) } if (cnt_move > 0) - memmove(&tcp_lost.hill[i + 1], - &tcp_lost.hill[i], + memmove(&tcp->lost.hill[i + 1], + &tcp->lost.hill[i], cnt_move * sizeof(struct sack_edges)); - tcp_lost.hill[i].l = tcp_seq_num; - tcp_lost.hill[i].r = tcp_seq_num + len; - tcp_lost.len = TCP_OPT_LEN_2 + cnt * TCP_OPT_LEN_8; + tcp->lost.hill[i].l = tcp_seq_num; + tcp->lost.hill[i].r = tcp_seq_num + len; + tcp->lost.len = TCP_OPT_LEN_2 + cnt * TCP_OPT_LEN_8; - tcp_update_ack_edge(); + tcp_update_ack_edge(tcp); }; /** * tcp_parse_options() - parsing TCP options + * @tcp: tcp stream * @o: pointer to the option field. * @o_len: length of the option field. */ -void tcp_parse_options(uchar *o, int o_len) +void tcp_parse_options(struct tcp_stream *tcp, uchar *o, int o_len) { struct tcp_t_opt *tsopt; uchar *p = o; @@ -467,7 +466,7 @@ void tcp_parse_options(uchar *o, int o_len) break; case TCP_O_TS: tsopt = (struct tcp_t_opt *)p; - rmt_timestamp = tsopt->t_snd; + tcp->rmt_timestamp = tsopt->t_snd; break; } @@ -479,7 +478,8 @@ void tcp_parse_options(uchar *o, int o_len) } } -static u8 tcp_state_machine(u8 tcp_flags, u32 tcp_seq_num, int payload_len) +static u8 tcp_state_machine(struct tcp_stream *tcp, u8 tcp_flags, + u32 tcp_seq_num, int payload_len) { u8 tcp_fin = tcp_flags & TCP_FIN; u8 tcp_syn = tcp_flags & TCP_SYN; @@ -500,21 +500,21 @@ static u8 tcp_state_machine(u8 tcp_flags, u32 tcp_seq_num, int payload_len) debug_cond(DEBUG_INT_STATE, "TCP STATE ENTRY %x\n", action); if (tcp_rst) { action = TCP_DATA; - current_tcp_state = TCP_CLOSED; + tcp->state = TCP_CLOSED; net_set_state(NETLOOP_FAIL); debug_cond(DEBUG_INT_STATE, "TCP Reset %x\n", tcp_flags); return TCP_RST; } - switch (current_tcp_state) { + switch (tcp->state) { case TCP_CLOSED: debug_cond(DEBUG_INT_STATE, "TCP CLOSED %x\n", tcp_flags); if (tcp_syn) { action = TCP_SYN | TCP_ACK; - tcp_seq_init = tcp_seq_num; - tcp_ack_edge = tcp_seq_num + 1; - tcp_lost.len = TCP_OPT_LEN_2; - current_tcp_state = TCP_SYN_RECEIVED; + tcp->seq_init = tcp_seq_num; + tcp->ack_edge = tcp_seq_num + 1; + tcp->lost.len = TCP_OPT_LEN_2; + tcp->state = TCP_SYN_RECEIVED; } else if (tcp_ack || tcp_fin) { action = TCP_DATA; } @@ -525,12 +525,12 @@ static u8 tcp_state_machine(u8 tcp_flags, u32 tcp_seq_num, int payload_len) tcp_flags, tcp_seq_num); if (tcp_fin) { action = action | TCP_PUSH; - current_tcp_state = TCP_CLOSE_WAIT; + tcp->state = TCP_CLOSE_WAIT; } else if (tcp_ack || (tcp_syn && tcp_ack)) { action |= TCP_ACK; - tcp_seq_init = tcp_seq_num; - tcp_ack_edge = tcp_seq_num + 1; - current_tcp_state = TCP_ESTABLISHED; + tcp->seq_init = tcp_seq_num; + tcp->ack_edge = tcp_seq_num + 1; + tcp->state = TCP_ESTABLISHED; if (tcp_syn && tcp_ack) action |= TCP_PUSH; @@ -541,15 +541,15 @@ static u8 tcp_state_machine(u8 tcp_flags, u32 tcp_seq_num, int payload_len) case TCP_ESTABLISHED: debug_cond(DEBUG_INT_STATE, "TCP_ESTABLISHED %x\n", tcp_flags); if (payload_len > 0) { - tcp_hole(tcp_seq_num, payload_len); + tcp_hole(tcp, tcp_seq_num, payload_len); tcp_fin = TCP_DATA; /* cause standalone FIN */ } if ((tcp_fin) && (!IS_ENABLED(CONFIG_PROT_TCP_SACK) || - tcp_lost.len <= TCP_OPT_LEN_2)) { + tcp->lost.len <= TCP_OPT_LEN_2)) { action = action | TCP_FIN | TCP_PUSH | TCP_ACK; - current_tcp_state = TCP_CLOSE_WAIT; + tcp->state = TCP_CLOSE_WAIT; } else if (tcp_ack) { action = TCP_DATA; } @@ -567,7 +567,7 @@ static u8 tcp_state_machine(u8 tcp_flags, u32 tcp_seq_num, int payload_len) debug_cond(DEBUG_INT_STATE, "TCP_FIN_WAIT_2 (%x)\n", tcp_flags); if (tcp_ack) { action = TCP_PUSH | TCP_ACK; - current_tcp_state = TCP_CLOSED; + tcp->state = TCP_CLOSED; puts("\n"); } else if (tcp_syn) { action = TCP_DATA; @@ -578,20 +578,20 @@ static u8 tcp_state_machine(u8 tcp_flags, u32 tcp_seq_num, int payload_len) case TCP_FIN_WAIT_1: debug_cond(DEBUG_INT_STATE, "TCP_FIN_WAIT_1 (%x)\n", tcp_flags); if (tcp_fin) { - tcp_ack_edge++; + tcp->ack_edge++; action = TCP_ACK | TCP_FIN; - current_tcp_state = TCP_FIN_WAIT_2; + tcp->state = TCP_FIN_WAIT_2; } if (tcp_syn) action = TCP_RST; if (tcp_ack) - current_tcp_state = TCP_CLOSED; + tcp->state = TCP_CLOSED; break; case TCP_CLOSING: debug_cond(DEBUG_INT_STATE, "TCP_CLOSING (%x)\n", tcp_flags); if (tcp_ack) { action = TCP_PUSH; - current_tcp_state = TCP_CLOSED; + tcp->state = TCP_CLOSED; puts("\n"); } else if (tcp_syn) { action = TCP_RST; @@ -615,6 +615,7 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len) u8 tcp_action = TCP_DATA; u32 tcp_seq_num, tcp_ack_num; int tcp_hdr_len, payload_len; + struct tcp_stream *tcp; /* Verify IP header */ debug_cond(DEBUG_DEV_PKT, @@ -643,11 +644,15 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len) return; } + tcp = tcp_stream_get(); + if (tcp == NULL) + return; + tcp_hdr_len = GET_TCP_HDR_LEN_IN_BYTES(b->ip.hdr.tcp_hlen); payload_len = tcp_len - tcp_hdr_len; if (tcp_hdr_len > TCP_HDR_SIZE) - tcp_parse_options((uchar *)b + IP_TCP_HDR_SIZE, + tcp_parse_options(tcp, (uchar *)b + IP_TCP_HDR_SIZE, tcp_hdr_len - TCP_HDR_SIZE); /* * Incoming sequence and ack numbers are server's view of the numbers. @@ -657,7 +662,7 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len) tcp_ack_num = ntohl(b->ip.hdr.tcp_ack); /* Packets are not ordered. Send to app as received. */ - tcp_action = tcp_state_machine(b->ip.hdr.tcp_flags, + tcp_action = tcp_state_machine(tcp, b->ip.hdr.tcp_flags, tcp_seq_num, payload_len); tcp_activity_count++; @@ -678,7 +683,7 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len) } else if (tcp_action != TCP_DATA) { debug_cond(DEBUG_DEV_PKT, "TCP Action (action=%x,Seq=%u,Ack=%u,Pay=%d)\n", - tcp_action, tcp_ack_num, tcp_ack_edge, payload_len); + tcp_action, tcp_ack_num, tcp->ack_edge, payload_len); /* * Warning: Incoming Ack & Seq sequence numbers are transposed @@ -687,6 +692,6 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len) net_send_tcp_packet(0, ntohs(b->ip.hdr.tcp_src), ntohs(b->ip.hdr.tcp_dst), (tcp_action & (~TCP_PUSH)), - tcp_ack_num, tcp_ack_edge); + tcp_ack_num, tcp->ack_edge); } } diff --git a/net/wget.c b/net/wget.c index f1dd7abeff6..c0a80597bfe 100644 --- a/net/wget.c +++ b/net/wget.c @@ -356,7 +356,8 @@ static void wget_handler(uchar *pkt, u16 dport, u32 tcp_seq_num, u32 tcp_ack_num, u8 action, unsigned int len) { - enum tcp_state wget_tcp_state = tcp_get_tcp_state(); + struct tcp_stream *tcp = tcp_stream_get(); + enum tcp_state wget_tcp_state = tcp_get_tcp_state(tcp); net_set_timeout_handler(wget_timeout, wget_timeout_handler); packets++; From patchwork Sat Aug 24 09:27:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Kshevetskiy X-Patchwork-Id: 1976361 X-Patchwork-Delegate: pbrobinson@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.a=rsa-sha256 header.s=selector2 header.b=cBYSjqWg; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WrWnt4MWLz1yXd for ; Sat, 24 Aug 2024 19:28:18 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 41D0588CA3; Sat, 24 Aug 2024 11:27:37 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.b="cBYSjqWg"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 3D984888C1; Sat, 24 Aug 2024 11:27:35 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,SPF_HELO_PASS, SPF_PASS,T_FILL_THIS_FORM_SHORT,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 Received: from EUR05-AM6-obe.outbound.protection.outlook.com (mail-am6eur05on20728.outbound.protection.outlook.com [IPv6:2a01:111:f403:2612::728]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id B8BAF888FD for ; Sat, 24 Aug 2024 11:27:32 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mikhail.kshevetskiy@genexis.eu ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=Ql6GzObaVYYw0StmmGIynq3fnMivHn/1SId2Zl2An0jckrNoDe0Y9Bhnl99AInHtIPJ52Nhk3ptLvSEphLxm6MqlUOqWvFaddkNh5NPmp7Ds3Hic67Ce22MoxjZJNa2IyiVZg9g3HJ7+sez5y/l/XseAr0e1fulUX987SkX2MfsGCgT2BN4/oovcbKSfxzQKe9uNBvjYJBfAceoj3T3SPJcRK6//j2ZdZhEEO62wzD5n8ZngeB30QtYkC+s2sJh7wy7zr5hospUf5IDKLJasuqrDtv+IuIySYeqVYZhA46S+uZfG+tRRGfLUkMnRX/ReKaT/R3nDYljrWuMeb+C+1Q== 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=uTUBvRZqEVyx1DbbaoVq2Sy9MR7atycMYEOaQ44ClTQ=; b=IzA+D0+sgMvq+Ns9lryu2e/U23Fjj75fBNY5nv5z4T41S5afVvJkG8mFrWmkl6ZoeG/TTNfrNSbbHlKzzV6Olga7Zd6r4k/GGVAmQ9xGezwFs4N5imEpLe68Wg+KdhGkEPDduMOwowazYrBpEKWCJxNzOlwCsjyoeZPyI8CZUqq0iUc9CwVqD17LKS282G7WvmJFT6UG0XLVUHqOijxBc+ZkzzD6mEk+563KJFrPQuuPOHPHmw0XdAv6DJAqyAoMn6NLJrIbyT4z1H1hLgoXY0hl+JexDgvmra5rZ+u0/cHWU9AA8i6DUwoe9xplpp+lStgxB8/1mWMLSyuLGuwbmQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=genexis.eu; dmarc=pass action=none header.from=iopsys.eu; dkim=pass header.d=iopsys.eu; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iopsys.eu; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=uTUBvRZqEVyx1DbbaoVq2Sy9MR7atycMYEOaQ44ClTQ=; b=cBYSjqWgGb8ajhmSUQqJ86Fn2RYhcPURRaNUvV9XZAJEa++ZxwwRtkJaPu1yMpyg/OSV6fyScAm5EbTWJqkxiH1l5gsWrOuaAN6D3Ws7e/E3JmEcgWsYQBzuAhuBv0xQre0aF6bReqXBQBUbhN1uVhXQZXX36twKrkO1OsKq592h2fgftmkfiozvifEkJkq3VtkXDCmBmDPYfDcQicgvFKjY0N+DlfXAsVj7rr5N+UwTpwBBlezEdpNdb8Gchjsg18WZMCljCRcAQEGFa9tCzvXzjx0LjE1jg4ncCVh1VgINUfYywjx+3RyiEiKqOWWgNLIWwhwzNdiunGo5pe4HIg== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=iopsys.eu; Received: from GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) by AS4PR08MB7601.eurprd08.prod.outlook.com (2603:10a6:20b:4ff::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7897.18; Sat, 24 Aug 2024 09:27:31 +0000 Received: from GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0]) by GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0%2]) with mapi id 15.20.7918.011; Sat, 24 Aug 2024 09:27:31 +0000 From: Mikhail Kshevetskiy To: Tom Rini , Joe Hershberger , Ramon Fried , Mattijs Korpershoek , Simon Glass , Heinrich Schuchardt , AKASHI Takahiro , Michal Simek , Francis Laniel , Anand Moon , Mikhail Kshevetskiy , Marek Vasut , Ilias Apalodimas , Masahisa Kojima , Sean Anderson , Baruch Siach , Yasuharu Shibata , u-boot@lists.denx.de Subject: [PATCH v5 04/11] net/tcp: add connection info to tcp_stream structure Date: Sat, 24 Aug 2024 12:27:09 +0300 Message-ID: <20240824092716.1042696-5-mikhail.kshevetskiy@iopsys.eu> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240824092716.1042696-1-mikhail.kshevetskiy@iopsys.eu> References: <20240824092716.1042696-1-mikhail.kshevetskiy@iopsys.eu> X-ClientProxiedBy: GV3P280CA0011.SWEP280.PROD.OUTLOOK.COM (2603:10a6:150:b::7) To GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: GV2PR08MB8121:EE_|AS4PR08MB7601:EE_ X-MS-Office365-Filtering-Correlation-Id: c7314675-8bd9-42c1-9eb9-08dcc41efa61 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|366016|376014|1800799024|52116014|7416014|921020|38350700014; X-Microsoft-Antispam-Message-Info: q9LiMGurAPiJoR5BwAh+jqOYclKyjhPIHQJSQwvmqSaOBW6gL8hBRKRrrxxy6qnvgbPIR29QFX5tWMlFX9To1g22+GnX83q9e32ikXaevpfzh0NZy8s0MzxN3LDqoueFrFJghoOCflNgo4P8PrKJO7+TiS/YWvJwH+xdlHoCbPgUEjfEomlTRaBAEgKlIZsvVPMOm6eYhdCLC25b86WuzYBr4xhzTF7bdOpZNrCru86MbDr3JsJtz9YtdTftDghlfu2w8vcC97wFbPGH0KASx4AgJZE73CaxguRxn8Ek6tepBxUkqk7w/Dux/dAHwnsH8qxoeZwb512tlEGgX8uskyMMTEGlVrS3lIeR6EE5ivGWSWS91+YAgIPuUO47BifKflpIwUDqzebbGiydtMipg82YDd7A2BwXgnJg04SgemzDRHl9Xbmz1u0o+t3U1bTl5Xs+GMugiFKVfWJVCh28Wlfm2hNZPGfgXyKT6JCACD/fzZ8TI0ru+sRijJO7eIbvZvmunjixKVgr9KWt5xS83ZurlaCws9qvrxnRsfDj6xD7ZmS1nMHt9ix/RWZIOQfuGW0rCe3zHSOqaQg9rNCLaU2GQyn//aAPP0e0KQ5OX0JSOs4jGNrpXWxaVBbKVSLwTETuzA/L9rMUI2h0/E1XgC7Z+YFtfxeY5JTFrOHBPipxOm9tZhf22ZoSUpXnkNVGyQSnZ08mb3ARy3qGySO+BGcgv61U3k+ldEbDR05Z/VRELRHZsqxuT7moXCuZGLdFN66avcGM0vlypFLg+Y7FtzzztCtBZo1oOkRpgmD9WEi94hXhq48lFwTcmBgJTRiU+j3DvPQbx6z1S5073sVX6mVeyzBVaA2fdUdY/57COCykfUAkbQfjk+1cClE9UIH9ddA0KOduXvqwy6Ub6rfTOcMEr4XE+3xILbwTSl9NwrYO0+MFMSOoR+XwDa86AIFwOKN+fDAwPO5EZyz2OsqvjiAIjOlWEYEZxHwYnGi99x4Q3HjQZpXcr93Z/1FvnqCljV8aIrlZd2eye3pkUjgUyoB1rDFCAOwPnffzLE8ZaJqvz+bHJ8kEwJhIdZ1wI51pJ6U+yln8OTc382iuVX1I+GT4CzlSsTteC6fqGZG/NutGwfmnlfYgUP/jOfvPoCFprv0a1nXEXimhG6G5bp812yx7hqeVX+7Qkruc2W/Mc95sk5rng6pzQ1YxW8cIStNXoNXXvwMbb4M0OVCJUabGr+shyVftSVd1Za63nN6HvRAOIL7K+BdnuZvZyS4TwWUjthw4OwL3bGGb82Jf9aXQrius8v2L3IaFfthLIXL05JTpmtEA5qPuUyiSJo3RyMqbpHJEM3ibkHku6yy/f3kEwAyehjV959ywMk4r5GbVwYhmhITr/yMs3bjk3XaNUI7l9J/ejk+gbPO/CrJ+mPlv3ekwo+CuEBdwrDoWlgfftO0= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:GV2PR08MB8121.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(366016)(376014)(1800799024)(52116014)(7416014)(921020)(38350700014); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: Vy4ub4Y9LAsvvgfl6H8Ah97M27lAo+EcmTpNd8IpTA7Gc4oE+H6WeR33VQSG197oZAznebLECrfOTf3Ng7yWHO5rNjfsXHN11sq52r3e9T2Y1ePbx9feUcr8Ca64O/iD13WY/ls+ygRTyTUf0g0m+eH7+0hD+Jk0Vuv65W/mn9BuYcEr1lXKwJynM2um53X+1O8w5zp5Fgr9/IrNi8OKOstNNacQjpTLzRqSYUoH1p2/SNrYjvmOQXq8cjAbS/MGmM6+JddiHiXlkf9hrL93cmd+hh/k7+sfGUCsb5ATsjvWQ3xUxgw4JPcUae9MNJHzZ+wENHiyrX4U+j/jTPwEPgzm/j301kNV72DQGAUsrUQ8F1s8bKrWuL7qpC1roaO3CNe2EWNdJW6zASKVrLhGhwTsflDkSv1Sj0cKvXQWqNK4mZvg9GXEg3eqm4j2sJVLxaGBJKAIo4+YdJ0O1/yagUWIcTqAcNdR47U0jT3fqnp8XkAWTvjo/k+XFEwVguEFl1DaM+YhjY02N9X23xUnbBmbZbpBi5FWDOvWKMRjhEnblldBy8/Gt+kI35j0Y2MFpdyIMSY/EJTQU1rIaX6OtI8p5+sBxCdcY10JiOnrk4n4kJLbjyrgKPDJJ9kEwwqz8Ils8M0eZmQu5xdtmZ2KNTnH59rCT29kmS6UsTSIXpxOpQRqKYZWukw03QflSg/69N6UotnZFE3Iwha8L5oiGl+mGhAGhdcb1+9oZXjFfkpI4jXi8OaZqHs7yL93j4bdbQA+rUQR68ynrvr3yR5oGQhmMgYWG2UyyiWGb9TnbfTXx96oQ+ARJu5Scqe2n+FJc0HReBjbmZuZZeZAA1wb+Yti10g5oFRSEXE7ld67oohVlxspzMxmh7gx4JvxJOIjkaDwoDq1HzxVP08bDC2GpXmLEhSRR0P3miE2sieLw2GjKNFj7bdmxQlnH+/8RMINekZvhbYsHrMFi2y1UzBXtRFdzaHzByRkW91iFTa1nI5oWUMf8Gdl7ISzkwQnK02sdO6GHANIN3LyDJkl1taZ+ke+hH2HhWkPMr8yxxzbCwFg9KJ4pWF3t27azjAz93IBSnBeZ8b8QC37oETp8p7saUup3u3Soc1xaWmtvZ1hkMOk7uBpvU3RVtYuZ/1SBWIavmxsmNumU0JdmpUzYgkrWw7LOv2oku+pbJ03MI9Abc4ZZWfjEw3yOcs+8gC+OC3Rg70r5k2VMv0/WQEZQrrIwnrBZis6PerbE9MMgWp9mKN4PNrydEIBv22e/JFHGlJI09tmGmTkXJd1Z6o50DBXKb80JWCIyqQ4bjfmrZ8t1iMGGyhQPYQa+YmGg0cJRye9f2HTuRxF6I+N52KQox/B0f/fSHnr8fw+ZQJ9qZzsJuwt1CiyMlfUL5139HDzNJkN46DLpbmoKmwLdAcP7qe0MwmkLwp10yMLAj/ji3ErjhiN+ea2LDrN4e8MHu5jmB4CmmXEXrqvnuXL2NAkHIjSA1sknllrdH/fKEVM31CHfIxs6x8G7uhsZqHIeSMQee7ppsR/v0J9rMdVZAcU71kX1xVOCh83lE4v9myPvb0cUph7KyBBVFhWDiWYxrvYe6EvejUFUItr5zVlxouTO0GyEyOAo4TMQiozkCDmyavdfes= X-OriginatorOrg: iopsys.eu X-MS-Exchange-CrossTenant-Network-Message-Id: c7314675-8bd9-42c1-9eb9-08dcc41efa61 X-MS-Exchange-CrossTenant-AuthSource: GV2PR08MB8121.eurprd08.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Aug 2024 09:27:31.0416 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 8d891be1-7bce-4216-9a99-bee9de02ba58 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: MvVnGjodGLnqzuIRvvGaklg9h6C2iUXLHvIZK4WtslaQ+VQSerygjrFjPa9Vn35uOiVa0E5uJKaGfEQb8CZuISxUyuE++BIyoTbF7F3MIWk= X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS4PR08MB7601 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Changes: * Avoid use net_server_ip in tcp code, use tcp_stream data instead * Ignore packets from other connections if connection already created. This prevents us from connection break caused by other tcp stream. Signed-off-by: Mikhail Kshevetskiy Reviewed-by: Simon Glass --- include/net.h | 5 +- include/net/tcp.h | 57 +++++++++++++++++--- net/fastboot_tcp.c | 50 +++++++++-------- net/net.c | 12 ++--- net/tcp.c | 131 ++++++++++++++++++++++++++++++++++----------- net/wget.c | 52 +++++++----------- 6 files changed, 204 insertions(+), 103 deletions(-) diff --git a/include/net.h b/include/net.h index bb2ae20f52a..b0ce13e0a9d 100644 --- a/include/net.h +++ b/include/net.h @@ -667,6 +667,7 @@ int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport, /** * net_send_tcp_packet() - Transmit TCP packet. * @payload_len: length of payload + * @dhost: Destination host * @dport: Destination TCP port * @sport: Source TCP port * @action: TCP action to be performed @@ -675,8 +676,8 @@ int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport, * * Return: 0 on success, other value on failure */ -int net_send_tcp_packet(int payload_len, int dport, int sport, u8 action, - u32 tcp_seq_num, u32 tcp_ack_num); +int net_send_tcp_packet(int payload_len, struct in_addr dhost, int dport, + int sport, u8 action, u32 tcp_seq_num, u32 tcp_ack_num); int net_send_udp_packet(uchar *ether, struct in_addr dest, int dport, int sport, int payload_len); diff --git a/include/net/tcp.h b/include/net/tcp.h index 14aee64cb1c..f224d0cae2f 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -279,6 +279,9 @@ enum tcp_state { /** * struct tcp_stream - TCP data stream structure + * @rhost: Remote host, network byte order + * @rport: Remote port, host byte order + * @lport: Local port, host byte order * * @state: TCP connection state * @@ -291,6 +294,10 @@ enum tcp_state { * @lost: Used for SACK */ struct tcp_stream { + struct in_addr rhost; + u16 rport; + u16 lport; + /* TCP connection state */ enum tcp_state state; @@ -305,16 +312,53 @@ struct tcp_stream { struct tcp_sack_v lost; }; -struct tcp_stream *tcp_stream_get(void); +void tcp_init(void); + +typedef int tcp_incoming_filter(struct in_addr rhost, + u16 rport, u16 sport); + +/* + * This function sets user callback used to accept/drop incoming + * connections. Callback should: + * + Check TCP stream endpoint and make connection verdict + * - return non-zero value to accept connection + * - return zero to drop connection + * + * WARNING: If callback is NOT defined, all incoming connections + * will be dropped. + */ +void tcp_set_incoming_filter(tcp_incoming_filter *filter); + +/* + * tcp_stream_get -- Get or create TCP stream + * @is_new: if non-zero and no stream found, then create a new one + * @rhost: Remote host, network byte order + * @rport: Remote port, host byte order + * @lport: Local port, host byte order + * + * Returns: TCP stream structure or NULL (if not found/created) + */ +struct tcp_stream *tcp_stream_get(int is_new, struct in_addr rhost, + u16 rport, u16 lport); + +/* + * tcp_stream_connect -- Create new TCP stream for remote connection. + * @rhost: Remote host, network byte order + * @rport: Remote port, host byte order + * + * Returns: TCP new stream structure or NULL (if not created). + * Random local port will be used. + */ +struct tcp_stream *tcp_stream_connect(struct in_addr rhost, u16 rport); + +enum tcp_state tcp_stream_get_state(struct tcp_stream *tcp); -enum tcp_state tcp_get_tcp_state(struct tcp_stream *tcp); -void tcp_set_tcp_state(struct tcp_stream *tcp, enum tcp_state new_state); -int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int dport, - int sport, int payload_len, +int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int payload_len, u8 action, u32 tcp_seq_num, u32 tcp_ack_num); /** * rxhand_tcp() - An incoming packet handler. + * @tcp: TCP stream * @pkt: pointer to the application packet * @dport: destination TCP port * @sip: source IP address @@ -324,8 +368,7 @@ int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int dport, * @action: TCP action (SYN, ACK, FIN, etc) * @len: packet length */ -typedef void rxhand_tcp(uchar *pkt, u16 dport, - struct in_addr sip, u16 sport, +typedef void rxhand_tcp(struct tcp_stream *tcp, uchar *pkt, u32 tcp_seq_num, u32 tcp_ack_num, u8 action, unsigned int len); void tcp_set_tcp_handler(rxhand_tcp *f); diff --git a/net/fastboot_tcp.c b/net/fastboot_tcp.c index d1fccbc7238..4d34fdc5a45 100644 --- a/net/fastboot_tcp.c +++ b/net/fastboot_tcp.c @@ -8,14 +8,14 @@ #include #include -static char command[FASTBOOT_COMMAND_LEN] = {0}; -static char response[FASTBOOT_RESPONSE_LEN] = {0}; +#define FASTBOOT_TCP_PORT 5554 + +static char command[FASTBOOT_COMMAND_LEN]; +static char response[FASTBOOT_RESPONSE_LEN]; static const unsigned short handshake_length = 4; static const uchar *handshake = "FB01"; -static u16 curr_sport; -static u16 curr_dport; static u32 curr_tcp_seq_num; static u32 curr_tcp_ack_num; static unsigned int curr_request_len; @@ -25,34 +25,37 @@ static enum fastboot_tcp_state { FASTBOOT_DISCONNECTING } state = FASTBOOT_CLOSED; -static void fastboot_tcp_answer(u8 action, unsigned int len) +static void fastboot_tcp_answer(struct tcp_stream *tcp, u8 action, + unsigned int len) { const u32 response_seq_num = curr_tcp_ack_num; const u32 response_ack_num = curr_tcp_seq_num + (curr_request_len > 0 ? curr_request_len : 1); - net_send_tcp_packet(len, htons(curr_sport), htons(curr_dport), + net_send_tcp_packet(len, tcp->rhost, tcp->rport, tcp->lport, action, response_seq_num, response_ack_num); } -static void fastboot_tcp_reset(void) +static void fastboot_tcp_reset(struct tcp_stream *tcp) { - fastboot_tcp_answer(TCP_RST, 0); + fastboot_tcp_answer(tcp, TCP_RST, 0); state = FASTBOOT_CLOSED; } -static void fastboot_tcp_send_packet(u8 action, const uchar *data, unsigned int len) +static void fastboot_tcp_send_packet(struct tcp_stream *tcp, u8 action, + const uchar *data, unsigned int len) { uchar *pkt = net_get_async_tx_pkt_buf(); memset(pkt, '\0', PKTSIZE); pkt += net_eth_hdr_size() + IP_TCP_HDR_SIZE + TCP_TSOPT_SIZE + 2; memcpy(pkt, data, len); - fastboot_tcp_answer(action, len); + fastboot_tcp_answer(tcp, action, len); memset(pkt, '\0', PKTSIZE); } -static void fastboot_tcp_send_message(const char *message, unsigned int len) +static void fastboot_tcp_send_message(struct tcp_stream *tcp, + const char *message, unsigned int len) { __be64 len_be = __cpu_to_be64(len); uchar *pkt = net_get_async_tx_pkt_buf(); @@ -63,12 +66,11 @@ static void fastboot_tcp_send_message(const char *message, unsigned int len) memcpy(pkt, &len_be, 8); pkt += 8; memcpy(pkt, message, len); - fastboot_tcp_answer(TCP_ACK | TCP_PUSH, len + 8); + fastboot_tcp_answer(tcp, TCP_ACK | TCP_PUSH, len + 8); memset(pkt, '\0', PKTSIZE); } -static void fastboot_tcp_handler_ipv4(uchar *pkt, u16 dport, - struct in_addr sip, u16 sport, +static void fastboot_tcp_handler_ipv4(struct tcp_stream *tcp, uchar *pkt, u32 tcp_seq_num, u32 tcp_ack_num, u8 action, unsigned int len) { @@ -77,8 +79,6 @@ static void fastboot_tcp_handler_ipv4(uchar *pkt, u16 dport, u8 tcp_fin = action & TCP_FIN; u8 tcp_push = action & TCP_PUSH; - curr_sport = sport; - curr_dport = dport; curr_tcp_seq_num = tcp_seq_num; curr_tcp_ack_num = tcp_ack_num; curr_request_len = len; @@ -89,17 +89,17 @@ static void fastboot_tcp_handler_ipv4(uchar *pkt, u16 dport, if (len != handshake_length || strlen(pkt) != handshake_length || memcmp(pkt, handshake, handshake_length) != 0) { - fastboot_tcp_reset(); + fastboot_tcp_reset(tcp); break; } - fastboot_tcp_send_packet(TCP_ACK | TCP_PUSH, + fastboot_tcp_send_packet(tcp, TCP_ACK | TCP_PUSH, handshake, handshake_length); state = FASTBOOT_CONNECTED; } break; case FASTBOOT_CONNECTED: if (tcp_fin) { - fastboot_tcp_answer(TCP_FIN | TCP_ACK, 0); + fastboot_tcp_answer(tcp, TCP_FIN | TCP_ACK, 0); state = FASTBOOT_DISCONNECTING; break; } @@ -111,12 +111,12 @@ static void fastboot_tcp_handler_ipv4(uchar *pkt, u16 dport, // Only single packet messages are supported ATM if (strlen(pkt) != command_size) { - fastboot_tcp_reset(); + fastboot_tcp_reset(tcp); break; } strlcpy(command, pkt, len + 1); fastboot_command_id = fastboot_handle_command(command, response); - fastboot_tcp_send_message(response, strlen(response)); + fastboot_tcp_send_message(tcp, response, strlen(response)); fastboot_handle_boot(fastboot_command_id, strncmp("OKAY", response, 4) == 0); } @@ -129,17 +129,21 @@ static void fastboot_tcp_handler_ipv4(uchar *pkt, u16 dport, memset(command, 0, FASTBOOT_COMMAND_LEN); memset(response, 0, FASTBOOT_RESPONSE_LEN); - curr_sport = 0; - curr_dport = 0; curr_tcp_seq_num = 0; curr_tcp_ack_num = 0; curr_request_len = 0; } +static int incoming_filter(struct in_addr rhost, u16 rport, u16 lport) +{ + return (lport == FASTBOOT_TCP_PORT); +} + void fastboot_tcp_start_server(void) { printf("Using %s device\n", eth_get_name()); printf("Listening for fastboot command on tcp %pI4\n", &net_ip); + tcp_set_incoming_filter(incoming_filter); tcp_set_tcp_handler(fastboot_tcp_handler_ipv4); } diff --git a/net/net.c b/net/net.c index 6c5ee7e0925..b33ea59a9fa 100644 --- a/net/net.c +++ b/net/net.c @@ -414,7 +414,7 @@ int net_init(void) /* Only need to setup buffer pointers once. */ first_call = 0; if (IS_ENABLED(CONFIG_PROT_TCP)) - tcp_set_tcp_state(tcp_stream_get(), TCP_CLOSED); + tcp_init(); } return net_init_loop(); @@ -899,10 +899,10 @@ int net_send_udp_packet(uchar *ether, struct in_addr dest, int dport, int sport, } #if defined(CONFIG_PROT_TCP) -int net_send_tcp_packet(int payload_len, int dport, int sport, u8 action, - u32 tcp_seq_num, u32 tcp_ack_num) +int net_send_tcp_packet(int payload_len, struct in_addr dhost, int dport, + int sport, u8 action, u32 tcp_seq_num, u32 tcp_ack_num) { - return net_send_ip_packet(net_server_ethaddr, net_server_ip, dport, + return net_send_ip_packet(net_server_ethaddr, dhost, dport, sport, payload_len, IPPROTO_TCP, action, tcp_seq_num, tcp_ack_num); } @@ -944,12 +944,12 @@ int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport, break; #if defined(CONFIG_PROT_TCP) case IPPROTO_TCP: - tcp = tcp_stream_get(); + tcp = tcp_stream_get(0, dest, dport, sport); if (tcp == NULL) return -EINVAL; pkt_hdr_size = eth_hdr_size - + tcp_set_tcp_header(tcp, pkt + eth_hdr_size, dport, sport, + + tcp_set_tcp_header(tcp, pkt + eth_hdr_size, payload_len, action, tcp_seq_num, tcp_ack_num); break; diff --git a/net/tcp.c b/net/tcp.c index 6646f171b83..0c32c5d7c92 100644 --- a/net/tcp.c +++ b/net/tcp.c @@ -26,6 +26,7 @@ static int tcp_activity_count; static struct tcp_stream tcp_stream; +static tcp_incoming_filter *incoming_filter; /* * TCP lengths are stored as a rounded up number of 32 bit words. @@ -40,40 +41,95 @@ static struct tcp_stream tcp_stream; /* Current TCP RX packet handler */ static rxhand_tcp *tcp_packet_handler; +#define RANDOM_PORT_START 1024 +#define RANDOM_PORT_RANGE 0x4000 + +/** + * random_port() - make port a little random (1024-17407) + * + * Return: random port number from 1024 to 17407 + * + * This keeps the math somewhat trivial to compute, and seems to work with + * all supported protocols/clients/servers + */ +static uint random_port(void) +{ + return RANDOM_PORT_START + (get_timer(0) % RANDOM_PORT_RANGE); +} + static inline s32 tcp_seq_cmp(u32 a, u32 b) { return (s32)(a - b); } /** - * tcp_get_tcp_state() - get TCP stream state + * tcp_stream_get_state() - get TCP stream state * @tcp: tcp stream * * Return: TCP stream state */ -enum tcp_state tcp_get_tcp_state(struct tcp_stream *tcp) +enum tcp_state tcp_stream_get_state(struct tcp_stream *tcp) { return tcp->state; } /** - * tcp_set_tcp_state() - set TCP stream state + * tcp_stream_set_state() - set TCP stream state * @tcp: tcp stream * @new_state: new TCP state */ -void tcp_set_tcp_state(struct tcp_stream *tcp, - enum tcp_state new_state) +static void tcp_stream_set_state(struct tcp_stream *tcp, + enum tcp_state new_state) { tcp->state = new_state; } -struct tcp_stream *tcp_stream_get(void) +void tcp_init(void) +{ + incoming_filter = NULL; + tcp_stream.state = TCP_CLOSED; +} + +void tcp_set_incoming_filter(tcp_incoming_filter *filter) +{ + incoming_filter = filter; +} + +static struct tcp_stream *tcp_stream_add(struct in_addr rhost, + u16 rport, u16 lport) +{ + struct tcp_stream *tcp = &tcp_stream; + + if (tcp->state != TCP_CLOSED) + return NULL; + + memset(tcp, 0, sizeof(struct tcp_stream)); + tcp->rhost.s_addr = rhost.s_addr; + tcp->rport = rport; + tcp->lport = lport; + tcp->state = TCP_CLOSED; + tcp->lost.len = TCP_OPT_LEN_2; + return tcp; +} + +struct tcp_stream *tcp_stream_get(int is_new, struct in_addr rhost, + u16 rport, u16 lport) { - return &tcp_stream; + struct tcp_stream *tcp = &tcp_stream; + + if (tcp->rhost.s_addr == rhost.s_addr && + tcp->rport == rport && + tcp->lport == lport) + return tcp; + + if (!is_new || !incoming_filter) || + !incoming_filter(rhost, rport, lport)) + return NULL; + + return tcp_stream_add(rhost, rport, lport); } -static void dummy_handler(uchar *pkt, u16 dport, - struct in_addr sip, u16 sport, +static void dummy_handler(struct tcp_stream *tcp, uchar *pkt, u32 tcp_seq_num, u32 tcp_ack_num, u8 action, unsigned int len) { @@ -222,8 +278,7 @@ void net_set_syn_options(struct tcp_stream *tcp, union tcp_build_pkt *b) b->ip.end = TCP_O_END; } -int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int dport, - int sport, int payload_len, +int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int payload_len, u8 action, u32 tcp_seq_num, u32 tcp_ack_num) { union tcp_build_pkt *b = (union tcp_build_pkt *)pkt; @@ -243,7 +298,7 @@ int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int dport, case TCP_SYN: debug_cond(DEBUG_DEV_PKT, "TCP Hdr:SYN (%pI4, %pI4, sq=%u, ak=%u)\n", - &net_server_ip, &net_ip, + &tcp->rhost, &net_ip, tcp_seq_num, tcp_ack_num); tcp_activity_count = 0; net_set_syn_options(tcp, b); @@ -264,13 +319,13 @@ int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int dport, b->ip.hdr.tcp_flags = action; debug_cond(DEBUG_DEV_PKT, "TCP Hdr:ACK (%pI4, %pI4, s=%u, a=%u, A=%x)\n", - &net_server_ip, &net_ip, tcp_seq_num, tcp_ack_num, + &tcp->rhost, &net_ip, tcp_seq_num, tcp_ack_num, action); break; case TCP_FIN: debug_cond(DEBUG_DEV_PKT, "TCP Hdr:FIN (%pI4, %pI4, s=%u, a=%u)\n", - &net_server_ip, &net_ip, tcp_seq_num, tcp_ack_num); + &tcp->rhost, &net_ip, tcp_seq_num, tcp_ack_num); payload_len = 0; pkt_hdr_len = IP_TCP_HDR_SIZE; tcp->state = TCP_FIN_WAIT_1; @@ -279,7 +334,7 @@ int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int dport, case TCP_RST: debug_cond(DEBUG_DEV_PKT, "TCP Hdr:RST (%pI4, %pI4, s=%u, a=%u)\n", - &net_server_ip, &net_ip, tcp_seq_num, tcp_ack_num); + &tcp->rhost, &net_ip, tcp_seq_num, tcp_ack_num); tcp->state = TCP_CLOSED; break; /* Notify connection closing */ @@ -290,7 +345,7 @@ int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int dport, debug_cond(DEBUG_DEV_PKT, "TCP Hdr:FIN ACK PSH(%pI4, %pI4, s=%u, a=%u, A=%x)\n", - &net_server_ip, &net_ip, + &tcp->rhost, &net_ip, tcp_seq_num, tcp_ack_num, action); fallthrough; default: @@ -298,7 +353,7 @@ int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int dport, b->ip.hdr.tcp_flags = action | TCP_PUSH | TCP_ACK; debug_cond(DEBUG_DEV_PKT, "TCP Hdr:dft (%pI4, %pI4, s=%u, a=%u, A=%x)\n", - &net_server_ip, &net_ip, + &tcp->rhost, &net_ip, tcp_seq_num, tcp_ack_num, action); } @@ -308,8 +363,8 @@ int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int dport, tcp->ack_edge = tcp_ack_num; /* TCP Header */ b->ip.hdr.tcp_ack = htonl(tcp->ack_edge); - b->ip.hdr.tcp_src = htons(sport); - b->ip.hdr.tcp_dst = htons(dport); + b->ip.hdr.tcp_src = htons(tcp->lport); + b->ip.hdr.tcp_dst = htons(tcp->rport); b->ip.hdr.tcp_seq = htonl(tcp_seq_num); /* @@ -332,10 +387,10 @@ int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int dport, b->ip.hdr.tcp_xsum = 0; b->ip.hdr.tcp_ugr = 0; - b->ip.hdr.tcp_xsum = tcp_set_pseudo_header(pkt, net_ip, net_server_ip, + b->ip.hdr.tcp_xsum = tcp_set_pseudo_header(pkt, net_ip, tcp->rhost, tcp_len, pkt_len); - net_set_ip_header((uchar *)&b->ip, net_server_ip, net_ip, + net_set_ip_header((uchar *)&b->ip, tcp->rhost, net_ip, pkt_len, IPPROTO_TCP); return pkt_hdr_len; @@ -616,19 +671,26 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len) u32 tcp_seq_num, tcp_ack_num; int tcp_hdr_len, payload_len; struct tcp_stream *tcp; + struct in_addr src; /* Verify IP header */ debug_cond(DEBUG_DEV_PKT, "TCP RX in RX Sum (to=%pI4, from=%pI4, len=%d)\n", &b->ip.hdr.ip_src, &b->ip.hdr.ip_dst, pkt_len); - b->ip.hdr.ip_src = net_server_ip; + /* + * src IP address will be destroyed by TCP checksum verification + * algorithm (see tcp_set_pseudo_header()), so remember it before + * it was garbaged. + */ + src.s_addr = b->ip.hdr.ip_src.s_addr; + b->ip.hdr.ip_dst = net_ip; b->ip.hdr.ip_sum = 0; if (tcp_rx_xsum != compute_ip_checksum(b, IP_HDR_SIZE)) { debug_cond(DEBUG_DEV_PKT, "TCP RX IP xSum Error (%pI4, =%pI4, len=%d)\n", - &net_ip, &net_server_ip, pkt_len); + &net_ip, &src, pkt_len); return; } @@ -640,12 +702,15 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len) pkt_len)) { debug_cond(DEBUG_DEV_PKT, "TCP RX TCP xSum Error (%pI4, %pI4, len=%d)\n", - &net_ip, &net_server_ip, tcp_len); + &net_ip, &src, tcp_len); return; } - tcp = tcp_stream_get(); - if (tcp == NULL) + tcp = tcp_stream_get(b->ip.hdr.tcp_flags & TCP_SYN, + src, + ntohs(b->ip.hdr.tcp_src), + ntohs(b->ip.hdr.tcp_dst)); + if (!tcp) return; tcp_hdr_len = GET_TCP_HDR_LEN_IN_BYTES(b->ip.hdr.tcp_hlen); @@ -676,9 +741,9 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len) "TCP Notify (action=%x, Seq=%u,Ack=%u,Pay%d)\n", tcp_action, tcp_seq_num, tcp_ack_num, payload_len); - (*tcp_packet_handler) ((uchar *)b + pkt_len - payload_len, b->ip.hdr.tcp_dst, - b->ip.hdr.ip_src, b->ip.hdr.tcp_src, tcp_seq_num, - tcp_ack_num, tcp_action, payload_len); + (*tcp_packet_handler) (tcp, (uchar *)b + pkt_len - payload_len, + tcp_seq_num, tcp_ack_num, tcp_action, + payload_len); } else if (tcp_action != TCP_DATA) { debug_cond(DEBUG_DEV_PKT, @@ -689,9 +754,13 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len) * Warning: Incoming Ack & Seq sequence numbers are transposed * here to outgoing Seq & Ack sequence numbers */ - net_send_tcp_packet(0, ntohs(b->ip.hdr.tcp_src), - ntohs(b->ip.hdr.tcp_dst), + net_send_tcp_packet(0, tcp->rhost, tcp->rport, tcp->lport, (tcp_action & (~TCP_PUSH)), tcp_ack_num, tcp->ack_edge); } } + +struct tcp_stream *tcp_stream_connect(struct in_addr rhost, u16 rport) +{ + return tcp_stream_add(rhost, rport, random_port()); +} diff --git a/net/wget.c b/net/wget.c index c0a80597bfe..ad5db21e97e 100644 --- a/net/wget.c +++ b/net/wget.c @@ -27,9 +27,8 @@ static const char http_eom[] = "\r\n\r\n"; static const char http_ok[] = "200"; static const char content_len[] = "Content-Length"; static const char linefeed[] = "\r\n"; -static struct in_addr web_server_ip; -static int our_port; static int wget_timeout_count; +struct tcp_stream *tcp; struct pkt_qd { uchar *pkt; @@ -137,22 +136,19 @@ static void wget_send_stored(void) int len = retry_len; unsigned int tcp_ack_num = retry_tcp_seq_num + (len == 0 ? 1 : len); unsigned int tcp_seq_num = retry_tcp_ack_num; - unsigned int server_port; uchar *ptr, *offset; - server_port = env_get_ulong("httpdstp", 10, SERVER_PORT) & 0xffff; - switch (current_wget_state) { case WGET_CLOSED: debug_cond(DEBUG_WGET, "wget: send SYN\n"); current_wget_state = WGET_CONNECTING; - net_send_tcp_packet(0, server_port, our_port, action, + net_send_tcp_packet(0, tcp->rhost, tcp->rport, tcp->lport, action, tcp_seq_num, tcp_ack_num); packets = 0; break; case WGET_CONNECTING: pkt_q_idx = 0; - net_send_tcp_packet(0, server_port, our_port, action, + net_send_tcp_packet(0, tcp->rhost, tcp->rport, tcp->lport, action, tcp_seq_num, tcp_ack_num); ptr = net_tx_packet + net_eth_hdr_size() + @@ -167,14 +163,14 @@ static void wget_send_stored(void) memcpy(offset, &bootfile3, strlen(bootfile3)); offset += strlen(bootfile3); - net_send_tcp_packet((offset - ptr), server_port, our_port, + net_send_tcp_packet((offset - ptr), tcp->rhost, tcp->rport, tcp->lport, TCP_PUSH, tcp_seq_num, tcp_ack_num); current_wget_state = WGET_CONNECTED; break; case WGET_CONNECTED: case WGET_TRANSFERRING: case WGET_TRANSFERRED: - net_send_tcp_packet(0, server_port, our_port, action, + net_send_tcp_packet(0, tcp->rhost, tcp->rport, tcp->lport, action, tcp_seq_num, tcp_ack_num); break; } @@ -339,10 +335,8 @@ static void wget_connected(uchar *pkt, unsigned int tcp_seq_num, /** * wget_handler() - TCP handler of wget + * @tcp: TCP stream * @pkt: pointer to the application packet - * @dport: destination TCP port - * @sip: source IP address - * @sport: source TCP port * @tcp_seq_num: TCP sequential number * @tcp_ack_num: TCP acknowledgment number * @action: TCP action (SYN, ACK, FIN, etc) @@ -351,13 +345,11 @@ static void wget_connected(uchar *pkt, unsigned int tcp_seq_num, * In the "application push" invocation, the TCP header with all * its information is pointed to by the packet pointer. */ -static void wget_handler(uchar *pkt, u16 dport, - struct in_addr sip, u16 sport, +static void wget_handler(struct tcp_stream *tcp, uchar *pkt, u32 tcp_seq_num, u32 tcp_ack_num, u8 action, unsigned int len) { - struct tcp_stream *tcp = tcp_stream_get(); - enum tcp_state wget_tcp_state = tcp_get_tcp_state(tcp); + enum tcp_state wget_tcp_state = tcp_stream_get_state(tcp); net_set_timeout_handler(wget_timeout, wget_timeout_handler); packets++; @@ -441,26 +433,13 @@ static void wget_handler(uchar *pkt, u16 dport, } } -#define RANDOM_PORT_START 1024 -#define RANDOM_PORT_RANGE 0x4000 - -/** - * random_port() - make port a little random (1024-17407) - * - * Return: random port number from 1024 to 17407 - * - * This keeps the math somewhat trivial to compute, and seems to work with - * all supported protocols/clients/servers - */ -static unsigned int random_port(void) -{ - return RANDOM_PORT_START + (get_timer(0) % RANDOM_PORT_RANGE); -} - #define BLOCKSIZE 512 void wget_start(void) { + struct in_addr web_server_ip; + unsigned int server_port; + image_url = strchr(net_boot_file_name, ':'); if (image_url > 0) { web_server_ip = string_to_ip(net_boot_file_name); @@ -513,8 +492,6 @@ void wget_start(void) wget_timeout_count = 0; current_wget_state = WGET_CLOSED; - our_port = random_port(); - /* * Zero out server ether to force arp resolution in case * the server ip for the previous u-boot command, for example dns @@ -523,6 +500,13 @@ void wget_start(void) memset(net_server_ethaddr, 0, 6); + server_port = env_get_ulong("httpdstp", 10, SERVER_PORT) & 0xffff; + tcp = tcp_stream_connect(web_server_ip, server_port); + if (tcp == NULL) { + net_set_state(NETLOOP_FAIL); + return; + } + wget_send(TCP_SYN, 0, 0, 0); } From patchwork Sat Aug 24 09:27:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Kshevetskiy X-Patchwork-Id: 1976362 X-Patchwork-Delegate: pbrobinson@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.a=rsa-sha256 header.s=selector2 header.b=X3kjxoA0; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WrWp46hLDz1yXd for ; Sat, 24 Aug 2024 19:28:28 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 9CF2288CD7; Sat, 24 Aug 2024 11:27:37 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.b="X3kjxoA0"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id E67E08890D; Sat, 24 Aug 2024 11:27:35 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,SPF_HELO_PASS, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 Received: from EUR05-AM6-obe.outbound.protection.outlook.com (mail-am6eur05on2072c.outbound.protection.outlook.com [IPv6:2a01:111:f403:2612::72c]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 7CDFF88C5D for ; Sat, 24 Aug 2024 11:27:33 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mikhail.kshevetskiy@genexis.eu ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=iQwq0VaSQpGtMrZKlC0kSUGAB/mYPGB3WYhCpE1h9JsFTBGvspNM44KZqfD8SGFuGN6nHRNfO94DB9oqLYLr5Of2PG1SMKl4DeEapaD2yW2NmHn3ZiYzizug1+lDlSfEPAclXaw1xDtubslp7lor1U8fXlGpmKGfG27sm65IgJSdwqw//5tYJgLJeZOL9x4IMakXImeXhHXhHk+Ttjb0iq8GsyICocPT/7yQrVL9VDBqRCclG6M9AqCqSPMq5ezz6ga+0FLkz4b9fES26ged9lesmv/4ObJd3SKde/TY0yhJCwUbxvzWeO8+HwXzYpZ11nAUcpHbDEuGRJiz1vPWwg== 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=Q00IswGxbCQx+1nod7QJu/ZY0jy4fSWCrsbK9hkN5WQ=; b=Rj/rruqKyNDaMD3EFd/oaBP2y/LS9UfTz57jnmHHpZKikvfCX6EN0gRCgwj6N+q0PH/gU6tOZwSpsa6kaH6mjS9Nyez7x7Bnm91aeZUkOCU3Hd4P2GGjmvYPjtm0UmaLznoukzNczIHdvT647m0yDiXKiudQLl1f2xymzH9NhV9zx7ufeRYLDrf55rZsuPG/yw2wvjO1636iBz1U85ZTKZPNML+iZP+QV7sgZhOKkx7/KxPUtPpbBmN48RsWZacqKaqU6KHOkPgbUk5nb0G8DyMTqEzYCKnGpVOgFqj+WkdUuzQ9JnM7+pmm6QuOnEQLXe/gAeX+qFZy4ThRAj0S9A== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=genexis.eu; dmarc=pass action=none header.from=iopsys.eu; dkim=pass header.d=iopsys.eu; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iopsys.eu; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Q00IswGxbCQx+1nod7QJu/ZY0jy4fSWCrsbK9hkN5WQ=; b=X3kjxoA0AWau5Nfn+L0JGS8A7TQYkvl9nhTTnTbobOm3iO1NLvy1hNTEGg1SfqmJdMWTBUX1TjAJomLQj9avxhQsJonoS0E2CHioG9pYgVNv1BhCDhSigjtZt2McwnoN5XHsA3DMmfp5jtC1lsHGVN/p07xf4nZky0870BUv+xzdKz5acngZYX7FQtwx7apaFVmiM09zkEH8Kncl5xrzw3OY3DiamWUjVU1aZKKmsWqnu7NGRYH8f15tm0+kiCHtD8CeoLnd0XYNbWTJOVs0bwxNjuTEpfHm8wi1J5i6+MI2sXQvp29UUg79z9HrjZkzjssXi2aeYag3nbUrz+Eyew== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=iopsys.eu; Received: from GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) by AS4PR08MB7601.eurprd08.prod.outlook.com (2603:10a6:20b:4ff::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7897.18; Sat, 24 Aug 2024 09:27:32 +0000 Received: from GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0]) by GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0%2]) with mapi id 15.20.7918.011; Sat, 24 Aug 2024 09:27:32 +0000 From: Mikhail Kshevetskiy To: Tom Rini , Joe Hershberger , Ramon Fried , Mattijs Korpershoek , Simon Glass , Heinrich Schuchardt , AKASHI Takahiro , Michal Simek , Francis Laniel , Anand Moon , Mikhail Kshevetskiy , Marek Vasut , Ilias Apalodimas , Masahisa Kojima , Sean Anderson , Baruch Siach , Yasuharu Shibata , u-boot@lists.denx.de Subject: [PATCH v5 05/11] net/tcp: rename ack_edge and seq_init to more common rcv_nxt and irs Date: Sat, 24 Aug 2024 12:27:10 +0300 Message-ID: <20240824092716.1042696-6-mikhail.kshevetskiy@iopsys.eu> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240824092716.1042696-1-mikhail.kshevetskiy@iopsys.eu> References: <20240824092716.1042696-1-mikhail.kshevetskiy@iopsys.eu> X-ClientProxiedBy: GV3P280CA0011.SWEP280.PROD.OUTLOOK.COM (2603:10a6:150:b::7) To GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: GV2PR08MB8121:EE_|AS4PR08MB7601:EE_ X-MS-Office365-Filtering-Correlation-Id: 1e90aff2-fe42-4c37-17d8-08dcc41efb25 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|366016|376014|1800799024|52116014|7416014|921020|38350700014; X-Microsoft-Antispam-Message-Info: 7TthzctXCXjjgsyWeDk+lQEXK320nmtfHfNWX8h6JtYLJpgVGomOlzjfKXYnAVDELMWlYaZBdeXcfJ9pCQyGhsI21eXQHA4Aw0Ph5oeCyPo7dseFF+/8NJB4n1j5h13hWZoAIKSwhcBvO1BkOkceP0IOD7XUumtSfcaYT2ZT3u/xnoCl1ZClv7PBr+xHkf8+QAe5KDu/IrJs5uJXe5u6sUdO7SzIQCc5xTK2jCW4py5aCQaGjVNYMgUA9++d2aaRCm1qjJ3EzqL+HyMUPx9lb/TyQN7G0OV/3s6EqBTswr5Mh3/19fzwO8rqDvm4Bn6mjVC4CmC7OQI5jw/p7MsT3z/ea7lXzjfOGwM2bYgN2S31kn9N0/ePIjAq+xIR7zLUhi73BnqxKcV+q7h/jEuqa2OWM1fh+sa7QRASD6ZOppASO9bVew48/AzxluScIU7EcihJdUFyx0M83wBAv4k+UEt6W1l7xskALgNm/tP8eb1tbHT1RrCaBJ/AyaiGv41US+dcoKSjnNbrciXAAWWBC+ZPugoqpu/Hb6xl0gjAyZTtZ0jFhYJtRGZTZdgpGWlEZmYHqEElOwfgay1N5nnsh5IF8Zf/sgospwMqRascwI+0x1+wipZb5gHSK4Yo1OVIqfi65HQ+7vbxPFCeyPqd41gOQlRrQMIczyLQPqT0AdSBEtSoQc3ju9nRNY352ox0XQUID6yI28VBHOsT5A8gRhI68CPHIacNJN1pn40hTtL5AujqSBOvgUZyGVB7X6lj88ew/H7j/DGhA4Uyb4Y1U8mKXQrqIckIwv3ElpfgIdEsiwbuJobjZle14C2ijokc5M49U15nkFsGhigxo+a8EoUPq+sdZ6YPS2ejEB4ovBOPw8PYeVGytB1M23s6ql5ZkGhhCTQWF4dLwqqJ+uCfCqpXrWoQ4/BkpKbpp8su+YyVdWTv0/u5dok6RUr0p0FZ4r57QJ3SU6QnJUbbFpHqVo0NERmh/pMRqsEY4oCxLSgim35zkC5CKb/z1MKEqgEps2stiOtiNKhMY0ROIdXa2rW8QbGTfAjYeFLtkzWzczGQorjKpJ/i5+YDhvatODf0gSswfp+EpncAwl2o89jS/x48bkJCmgipWSWshXd400OLkBoKWrjbApyzi+DwVY4YAhJawNQXqdRePkjjZ0oRM5AV54/4JXJcubQesUS+az2ey4yEfaAOYr0IC9VwubtL/FUSQah2q9/p6yj/XW1F8Qj4tAbXE1A3qY/MjppvQAISlh2xay0Y+85KU28s9RN5mdefm82f4OggibYIjstk5DzqanZ+OU+z0bEn6uRJDCmBKA8fWaFYrkGQl6a7tVTNjyqE9TlpHxRGMpBvsJWggMQETAQAiWGvFbkqTRiiVUDJTdT5DjXPN56IxH3xNGtOLJCcmD3pGSkzt1YaheuExaN+wyx8dRL7aYp848dZVvo= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:GV2PR08MB8121.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(366016)(376014)(1800799024)(52116014)(7416014)(921020)(38350700014); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: Y4TnyDeTkkjfjdETTPkqbGi9YiyIRcC83MNkOMhDkk3GYDEIK2cfdconW7vL+P1GYdGIx8yRLcW5LPybNtuKknSUGU8OgIiC7ZovDa6uVxGLsZhs4Aogc5T9kHEmUxK6a9lDErZa3uVTYo/oD2eCu/GYT0rty+r5/QX7UeYxIb/LS1qZNLWBfqZlq9wCKV72yTy/UYABERMpyHr6oSKQLYYL7k9MFxEJzn8gNfkdKzoVTuLsrpaxyoCHYX4R7PbGL3R31y9ZS2rtrwC1YxCOXNhR9ic5j0+iRqieplvPABk09JvYwhARJ5a7R5QnyOKlfXKIyuhjXNrWz0P0M2P1cpdVSsbG6REYT7rOZbE70lUm4VtutW8JJGsicCjWZmIjFrpYMXJ5aIQ0aC4Ratvn2YemLofIRMbttxQrBPyneaPRf0/noxVDRQP/09tdONcBkjbnHXOWO5RdGqLMxJrrqqypXymao/1APKl20mYFwomzFJC0YKiJWX4kCagPiP8YnPBCUc0/BtQfk01wpxwF7f/4O02E/0/y0J77pxrfOZBc9LyIHzC/PAVmXOMGnvsgwLx05eMY+Yu9hyRgZlfYG0uuMaS+AiGq8anb1TCaU4IaKp9TLGV83QrbM3i0w1zK5KN/ixFR3C2mxtYZdVzbpbTG15U5QxEeoMnDr3SLuLWK7Lak0sdJzDuMMV8qZ535ZP01rI8yE/wVyIVC5MCbfMG/OrSk2eC2QuSjt83GUvJsrrx/09PT41HyE+HR+kHMh6ZdZCvezVpgzs+juKFFxaTixuBWESsVtLftvR3IQ+0a0NbiQBvAKJqXxukW4HPYcqzNpb1lRm4duf5r9myzJsaS6lb/gBvOqF6EHiVpzjFV5HqqfU54aIpLVaZzrxbq0aU2yA0mP0x8YqeRZK2v7XWwJXYIgd1973JHU6433yM6TjPcZ4AvE5zhAQL+PdgZafbo+wBhV8SvYMBqOPD5T2N+IjsI+aN1qMA5dUUpBJ2j9mOZUeAUmEAf2WEDKEn4YABtXGm0gWibg9Mv6oNYirQTF5+wFa8MMSaLRR0Svv647M+5/09emHq2A2Y/FiL8bo+Sk34BvAtP4RrdZuB7xnokb40JX+YlB8xFpHum2VoQQR5eB2VwWjzvQ2ssM9+yruETPb8sECA9gB180vS18Bgw+HuwBLy8hq9lEfoC3HRCF4l8kGQ0VYIYL4+Lh4pzkF8YLKI0SXZ8LzmAK/sxyb7s/DKhZ1IJxSrM3znpElVeweFYVKat10KnKNOwUNL0UjrkpnhPTnG28ft4DaBmH24uzpWT4RVDc/e/WSsy8fcHouJ8chiVlcLLYZjaX/t2f5Hse7OVhu0jDk+YFK+8hQAyaCxuZhwHJuiomGcKgFli7Kq6/3v2dG/0DWA+LyfPd/J/llqGMoR46pJv22sQtuvzF2r5rQ7ABThEEBIW2QKM/ImeSQXntU3d3CAsTxSSHu2DxtgaQkln+df518MykEP/OQi0JTHBGy1QgWJl7hhE/kGhzfKNfTe7GEUbYXPTyH0RNM0o+NUqtB8liCaQRiqH5A1ynDjZVOSFzZCgLB26N9MdTV3ybKu6/2BxXvOEjL3OZAxyasUS5tnN4i7MIipsLbMkD8P/xdZlm7aWJMw= X-OriginatorOrg: iopsys.eu X-MS-Exchange-CrossTenant-Network-Message-Id: 1e90aff2-fe42-4c37-17d8-08dcc41efb25 X-MS-Exchange-CrossTenant-AuthSource: GV2PR08MB8121.eurprd08.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Aug 2024 09:27:32.2811 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 8d891be1-7bce-4216-9a99-bee9de02ba58 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: +wK7M0MLubTP8S7wIyKO/rHGUz19Vy81SsxcjdFbl8RhhoV/TYb6a26sJ3H0+Yr9sqZbko+Ixbwtg3raHmucsT1xxpmiMuSJl57a6u8bHi8= X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS4PR08MB7601 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Use the names from RFC 9293 Signed-off-by: Mikhail Kshevetskiy Reviewed-by: Simon Glass --- include/net/tcp.h | 8 ++++---- net/tcp.c | 32 ++++++++++++++++---------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index f224d0cae2f..0694af9d5b1 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -285,8 +285,8 @@ enum tcp_state { * * @state: TCP connection state * - * @seq_init: Initial receive sequence number - * @ack_edge: Receive next + * @irs: Initial receive sequence number + * @rcv_nxt: Receive next * * @loc_timestamp: Local timestamp * @rmt_timestamp: Remote timestamp @@ -301,8 +301,8 @@ struct tcp_stream { /* TCP connection state */ enum tcp_state state; - u32 seq_init; - u32 ack_edge; + u32 irs; + u32 rcv_nxt; /* TCP option timestamp */ u32 loc_timestamp; diff --git a/net/tcp.c b/net/tcp.c index 0c32c5d7c92..7e445eaffd6 100644 --- a/net/tcp.c +++ b/net/tcp.c @@ -360,9 +360,9 @@ int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int payload_len, pkt_len = pkt_hdr_len + payload_len; tcp_len = pkt_len - IP_HDR_SIZE; - tcp->ack_edge = tcp_ack_num; + tcp->rcv_nxt = tcp_ack_num; /* TCP Header */ - b->ip.hdr.tcp_ack = htonl(tcp->ack_edge); + b->ip.hdr.tcp_ack = htonl(tcp->rcv_nxt); b->ip.hdr.tcp_src = htons(tcp->lport); b->ip.hdr.tcp_dst = htons(tcp->rport); b->ip.hdr.tcp_seq = htonl(tcp_seq_num); @@ -396,10 +396,10 @@ int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int payload_len, return pkt_hdr_len; } -static void tcp_update_ack_edge(struct tcp_stream *tcp) +static void tcp_update_rcv_nxt(struct tcp_stream *tcp) { - if (tcp_seq_cmp(tcp->ack_edge, tcp->lost.hill[0].l) >= 0) { - tcp->ack_edge = tcp->lost.hill[0].r; + if (tcp_seq_cmp(tcp->rcv_nxt, tcp->lost.hill[0].l) >= 0) { + tcp->rcv_nxt = tcp->lost.hill[0].r; memmove(&tcp->lost.hill[0], &tcp->lost.hill[1], (TCP_SACK_HILLS - 1) * sizeof(struct sack_edges)); @@ -434,7 +434,7 @@ void tcp_hole(struct tcp_stream *tcp, u32 tcp_seq_num, u32 len) tcp_seq_num = tcp->lost.hill[i].l; } if (tcp_seq_cmp(tcp->lost.hill[i].r, tcp_seq_num + len) >= 0) { - tcp_update_ack_edge(tcp); + tcp_update_rcv_nxt(tcp); return; } @@ -463,12 +463,12 @@ void tcp_hole(struct tcp_stream *tcp, u32 tcp_seq_num, u32 len) } } - tcp_update_ack_edge(tcp); + tcp_update_rcv_nxt(tcp); return; } if (i == TCP_SACK_HILLS) { - tcp_update_ack_edge(tcp); + tcp_update_rcv_nxt(tcp); return; } @@ -489,7 +489,7 @@ void tcp_hole(struct tcp_stream *tcp, u32 tcp_seq_num, u32 len) tcp->lost.hill[i].r = tcp_seq_num + len; tcp->lost.len = TCP_OPT_LEN_2 + cnt * TCP_OPT_LEN_8; - tcp_update_ack_edge(tcp); + tcp_update_rcv_nxt(tcp); }; /** @@ -566,8 +566,8 @@ static u8 tcp_state_machine(struct tcp_stream *tcp, u8 tcp_flags, debug_cond(DEBUG_INT_STATE, "TCP CLOSED %x\n", tcp_flags); if (tcp_syn) { action = TCP_SYN | TCP_ACK; - tcp->seq_init = tcp_seq_num; - tcp->ack_edge = tcp_seq_num + 1; + tcp->irs = tcp_seq_num; + tcp->rcv_nxt = tcp_seq_num + 1; tcp->lost.len = TCP_OPT_LEN_2; tcp->state = TCP_SYN_RECEIVED; } else if (tcp_ack || tcp_fin) { @@ -583,8 +583,8 @@ static u8 tcp_state_machine(struct tcp_stream *tcp, u8 tcp_flags, tcp->state = TCP_CLOSE_WAIT; } else if (tcp_ack || (tcp_syn && tcp_ack)) { action |= TCP_ACK; - tcp->seq_init = tcp_seq_num; - tcp->ack_edge = tcp_seq_num + 1; + tcp->irs = tcp_seq_num; + tcp->rcv_nxt = tcp_seq_num + 1; tcp->state = TCP_ESTABLISHED; if (tcp_syn && tcp_ack) @@ -633,7 +633,7 @@ static u8 tcp_state_machine(struct tcp_stream *tcp, u8 tcp_flags, case TCP_FIN_WAIT_1: debug_cond(DEBUG_INT_STATE, "TCP_FIN_WAIT_1 (%x)\n", tcp_flags); if (tcp_fin) { - tcp->ack_edge++; + tcp->rcv_nxt++; action = TCP_ACK | TCP_FIN; tcp->state = TCP_FIN_WAIT_2; } @@ -748,7 +748,7 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len) } else if (tcp_action != TCP_DATA) { debug_cond(DEBUG_DEV_PKT, "TCP Action (action=%x,Seq=%u,Ack=%u,Pay=%d)\n", - tcp_action, tcp_ack_num, tcp->ack_edge, payload_len); + tcp_action, tcp_ack_num, tcp->rcv_nxt, payload_len); /* * Warning: Incoming Ack & Seq sequence numbers are transposed @@ -756,7 +756,7 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len) */ net_send_tcp_packet(0, tcp->rhost, tcp->rport, tcp->lport, (tcp_action & (~TCP_PUSH)), - tcp_ack_num, tcp->ack_edge); + tcp_ack_num, tcp->rcv_nxt); } } From patchwork Sat Aug 24 09:27:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Kshevetskiy X-Patchwork-Id: 1976364 X-Patchwork-Delegate: pbrobinson@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.a=rsa-sha256 header.s=selector2 header.b=FOLF+FHm; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WrWpS6ppJz1yXd for ; Sat, 24 Aug 2024 19:28:48 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 64FED88C42; Sat, 24 Aug 2024 11:27:40 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.b="FOLF+FHm"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id BDF5288CED; Sat, 24 Aug 2024 11:27:38 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,SPF_HELO_PASS, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 Received: from EUR05-AM6-obe.outbound.protection.outlook.com (mail-am6eur05on20701.outbound.protection.outlook.com [IPv6:2a01:111:f403:2612::701]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 719A8888C1 for ; Sat, 24 Aug 2024 11:27:35 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mikhail.kshevetskiy@genexis.eu ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=MHoebV8HkwX2/tYtI1S1Ktx17tybUuLj7RdplM2Ah3/qh8KYv94/v1E3t49QrK6jqgkVTFrSKsiFYM+y1DQ/i5xxCtGXNo26aA9HVnYHJGWaLc8ms8Aw0Fm22fzes9yxwlBcsXn2nTvUNsUT6JZjKsALVXMQ8Vmv/NhzD1DRvJBOic6jv1twS8a3Jkh3cL5zIB6k2uNEBd+WP+NerGVu4VIECAgEMGy6o2PeCt8khFu826XZhCG+UJNA2DfmecR04gCYpWfeAFz7rkkaFgQa5qm3abLUDeOyUWDDsHmrcsNXBnhkx+cQnoVSOjE7hYCcWshU7y31AJ4WC9SfPNAvYg== 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=xqbeg/gG4qFJFTyLw7FDBHCqyAdsa1rowTcy+dlv/pg=; b=QJ8UH14eYj1XCOwi8ZDb092eriQiHPwqajok6jYDiklQMvjWBrG4JuAT3pjX6nT+pWN6naD9riN8MjDiOmxRfMlrKr465dpHcznhDLJusJd//kg016HxidFh1TzD8nVgaE1kfPaVD3PdoMTAyjTJKzTsDKwARLWLOn2gbIiQe32x5ipLQXc+jySpYxn2b4iTbqeC+7B2SAPg6yvI0+AraiMvcXLGPNi3bWG72yyW3zUYYqJb63ZzSjmBDl5C33DCs34XShdDgEKGxw0R+a298wXKOVapA5C5/Bxkcn7jDXyAd7SaZ59x9Ioj1jYuaCD2y/UD0Ej/QlgPLA3NerVVIA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=genexis.eu; dmarc=pass action=none header.from=iopsys.eu; dkim=pass header.d=iopsys.eu; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iopsys.eu; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=xqbeg/gG4qFJFTyLw7FDBHCqyAdsa1rowTcy+dlv/pg=; b=FOLF+FHmaHh9oFRu8mznk1DXVV0Rejk2l8mjNQgurwV0IQ+Nnjthp+xnlUEUAY4tq4B76j50b2p1evo3e4EROkKX+MHluL1shiVWHZGr+lAvdoGSmlYAA+muHKyKryjorCBvrk3mSx/VJGq3nUOfHGIPbduUhpJhyN+ELbiYkgGFYY1hl9AsJszPkVnv0XL7J8gO8iQO9Lr/9++40Qr/eiIbe/B9ZAd71uS6gHpgrKJhSlpqs08rqusaVRkLeB3P11APcTdyVWbP+MDIiB+oSp0gzm75tmNLRJ/yOtP4euwHZGQyT1Bphk4y9pq94EDBnRwxW2xsSzVUvFYXCT8gWA== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=iopsys.eu; Received: from GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) by AS4PR08MB7601.eurprd08.prod.outlook.com (2603:10a6:20b:4ff::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7897.18; Sat, 24 Aug 2024 09:27:33 +0000 Received: from GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0]) by GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0%2]) with mapi id 15.20.7918.011; Sat, 24 Aug 2024 09:27:33 +0000 From: Mikhail Kshevetskiy To: Tom Rini , Joe Hershberger , Ramon Fried , Mattijs Korpershoek , Simon Glass , Heinrich Schuchardt , AKASHI Takahiro , Michal Simek , Francis Laniel , Anand Moon , Mikhail Kshevetskiy , Marek Vasut , Ilias Apalodimas , Masahisa Kojima , Sean Anderson , Baruch Siach , Yasuharu Shibata , u-boot@lists.denx.de Subject: [PATCH v5 06/11] net/tcp: improve tcp framework, use better state machine Date: Sat, 24 Aug 2024 12:27:11 +0300 Message-ID: <20240824092716.1042696-7-mikhail.kshevetskiy@iopsys.eu> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240824092716.1042696-1-mikhail.kshevetskiy@iopsys.eu> References: <20240824092716.1042696-1-mikhail.kshevetskiy@iopsys.eu> X-ClientProxiedBy: GV3P280CA0011.SWEP280.PROD.OUTLOOK.COM (2603:10a6:150:b::7) To GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: GV2PR08MB8121:EE_|AS4PR08MB7601:EE_ X-MS-Office365-Filtering-Correlation-Id: 6b6f799e-84ef-43cb-e0ac-08dcc41efbe3 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|366016|376014|1800799024|52116014|7416014|921020|38350700014; X-Microsoft-Antispam-Message-Info: aE1JJpYTIyaiGMCIBLJbKpZCxmxiIM3hAg887ZdpFU+FR4ikEhEzYjBfsV8ewfsfXlrKERhWXFyPw5C2e49px++X14v3OklvxgfmAW+pqyXsIhxbzgok5GCgtdOWUf6uIiL8WCJjoa0/O9RHBVDy8LwWev1TcQDSte8zrU7Xpv1Kwi2ncwCygPuLLNh75Wb2hXL+NQQaEmgP713DNvekLrII0Z2KdnPnngfs+u9h0YYGcQt5wmOtd7NgaaqYkcciiyGS5memYWfdlYy2/sCtl9gurSYLtlh+TqwS6gf55a9ovXjCtN2qAekho8coow1+SR8YvK6Zz9TM/fOfbl9V4pwCixBYKFAHEWxh0dtDFfVvoSGWiCgJAeggUlBHTQfwR18N5QY2WMjRA/s8Odg4TU13+D0jMYMffSUWkFyfsgDn2rOj0AAmiXaPiOEjuUWKtj4q8zotTi1myj15ckveK0GffYPLAlq9NbQ6/spm0wQUUQefQnHEBCWSX+t+Fwj9EOqhz+XQjn+od1H4wV3xE8RpV3lzAVDfwANSjGyIC8LXrB2vKe0DsYhis+6qsPmwOgN4zAQv5BOOxsPCCBpucS7usVp7NfWgcMKg7eGqmAbPVSW+qxdRt/EphIaW3Ofk7Wp7euRwb617SN1NT1xN6TVEgfg9PHapQhTLNelYPEdfmp1HjxHnNdDwdAj55bJw3S16i3csryjaQsqM699zmXOEq4YtdHvQM1NLANzwLsXzvbcumOeQy7T5nA8SXGFa8PtqYN57u7ZvBOwISaiylY7vLLXmEnr23T13/MaBeQFjBHX//OH8E+1S+1fgqMvuzvxCg+5gqj+c2KX33UcLrmh4YGrE3llXTuJgFOy33fZbyEBCo0rhuoxwoCRHgGQs+MhkPqtmr3seRMUB2jPOHDKMEbcyk+Vpf7QQnAt1sOQvaDkY9F1cxEVV/zSluwpgvO3qCh/jqYfWa4iOfPPbTPyjxPXuTyFOcRi1GSd7P/Nq+QB/K+3C+Wc2kUhjPA6pj6F0hrwnPeGqz7uCOJO/4gGpKUxwQu09jugUyPKUZi/6Q43be2DptME4s9DA7qpSRMN1OE8iqGpHfZZURrDiRV/VUjdghGH0ISuUjf7bQ76k+/i00UOD/cFRCGasbpL1xE0CD2/81iCmu9nEEvv0eYMBnpNvK2omUjuJFF8H6Fny21iYkQoR6eDyW23PoCQQUlanp9PmQ5odR+fLQA1yFveRypTrZXdwp5AEZ0B4LoaG97BSvrzNXade7Z6QuXK99vOj0Ik8c1Vp+i/WhizncUtIR0eGQo/a8WZkn8/ePqLUCJnJbdhcub5vqLv4SellWlLF0wDJwZc7S5YtwfBKcuFMEvsxhD/Fg+CvA5jnQqm2HIeNxAOOk1BmlWkc9FLjKHqqiS2yStxCtSaakKL//v+vfmZLDZwpLk8z33bZ+GE= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:GV2PR08MB8121.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(366016)(376014)(1800799024)(52116014)(7416014)(921020)(38350700014); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: rD9TMH6e4LerzyyBYLSjAv4waK29Ao8buZS8oMwQlRbh+/oCLmVilW79aNBTm1u2p35M68zvGSExboRiecbx8qI0Y3P+s1iOpNU/73SuFisPkf2TXm5qQlTeJNJsLfuIIDaurSfUmlmSABRih0dYG3vWWtQmuHal45028lKpQIFy6C56DAnv2T+NOsgtKnF0Gu/H3q+QGo+pRcz+jsm+y06vsr1PfVfF67B07t1Hg1uEyf8uxyOAkYx/pqgkg/j4l1Z1qbhAR/Yhr8tAylQMMnNnfO8jlCV2PeUQOK85QhCZIDjm/dkneDxLRX65L0UtNribfdwt24LUeh3B+QUJ+3bW9e4qTuC55GrJOTrQWj40biYeNXJe8RMRLMVvJ0ZEJYdZq2safa06CvPJ1aDR+wlJIqRch1gfCUjT2MzLw5vIm6YAzr7htUzVcdrBk9yUNy6pP7tyD3PkkRvq4fuyux77zt2/QaFnPArU6sER72grEazpu8lbAGZPVH4YcY4FtaElMrK5H7+T8HegIj0yjKdVftK3Kv3QL8bK2z2Wy7NatbWK5UnLwcmo/pkhw24vai5O/y9+pQuCLtwYIRDbb1dDUZKmwexejS9s7k+ewQTqTUT1udNR+sCwc6Dc8Z/rikmtiuVrUkITe4tBej8EiaOdw58rDdF2/aelwCL+2UCTMef0Hp5LiC7UXUOArHYyQxz/SPpcX+GE3/3rfUYbJAH9qbs19imQnpb5D3euGG+9Vcoi70wGKZcUSAdSU/t9DoW80jQD9Lifh3UojCQ7gAbESQBKYty3uvnsYkYQnmE16Z/Koe7BuX9I4ONQz2WRR0rg3F8LQR5r09VX4pAlp7O8xJpoBHu0UwZ+1FjArp3n2VaJkZvy7QmZQjBYLTf3UptQsSAstUyIDXNbzDrH4eEemsWsV4noxcfVid7GEgH9OfV/u3RgjJPrh39k6rMxfsRqBjL0cDtVU/a6ZLa0U75IHjFHMMoh+HEaqhGhJ6ECbeGlWDpNjIhSNZ3LYl0Q+3dfbSb6VEyjHk2f+cj2WnJfOFAN416kNtUCuRaG9hg/+5OqihBhzLV6572PrLX/KtUueON3lETnPc0XTnKoWyTqE/VivFtC5FBItAhmOSW0NM5Rg8WeAOWWxiwUNOIQq6+rH288Cbf7aGmW2LY8ZjInlQgyitkECEGmP09xbHFkkfXKz21bb/lW1RRRP0rFJo22TxDKrctkr/yUgJ4UegzdAwN5BAhttyr0gKYTdauehZ4j/cmHaefkpw+aQn8bzB1KoEP7Rp/sDiv8VNm/m2ru7hXIWFBeY2vz55eP7MF4150nM5LcGwD/TH/xIJXFZbbgEgnxfT9ZG7nxX41BfhZQJWD3w2E73vgtn4fviEJTsYX8G+OlDJY9rECdQO9aLyP24Dq97x6mdLOGGjTN/i4HnbC3SEcvw/fvwA2F2b0McXPLadjIDTLaSYu8UWxTaYnvjwU4wDyZQzNMc20w5vsVuN2ybtaWPrPpoTeq+JCdGSgagvszGQwKRaIkWihGSTRn4od0F9F38m+8aEJ0ZJukHbOrwHxHDHvkzZe0K42nx7UJ2rGjg82a8TLZVDUnrbKI4OOrrNX70g9dGmW4wFnL2VsI1UnKJFBUu2KbCPc= X-OriginatorOrg: iopsys.eu X-MS-Exchange-CrossTenant-Network-Message-Id: 6b6f799e-84ef-43cb-e0ac-08dcc41efbe3 X-MS-Exchange-CrossTenant-AuthSource: GV2PR08MB8121.eurprd08.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Aug 2024 09:27:33.5788 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 8d891be1-7bce-4216-9a99-bee9de02ba58 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: REOE88SnkNfJ+cQm/QXE6nPgbzcSm78A1nHtEx8Opjk+2xUFgqi2m5fGp1iqb/1d9CJwk+s5rrq3uIVC5DUjHnAj6LOOkQLiVoo0kdRjY7g= X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS4PR08MB7601 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Changes: * Fix initial send sequence always zero issue * Use state machine close to RFC 9293. This should make TCP transfers more reliable (now we can upload a huge array of data from the board to external server) * Improve TCP framework a lot. This should make tcp client code much more simple. * rewrite wget with new tcp stack * rewrite fastboot_tcp with new tcp stack It's quite hard to fix the initial send sequence (ISS) issue with the separate patch. A naive attempt to fix an issue inside the tcp_set_tcp_header() function will break tcp packet retransmit logic in wget and other clients. Example: Wget stores tcp_seq_num value before tcp_set_tcp_header() will be called and (on failure) retransmit the packet with the stored tcp_seq_num value. Thus: * the same ISS must allways be used (current case) * or tcp clients needs to generate a proper ISS when required. A proper ISS fix will require a big redesing comparable with a this one. Signed-off-by: Mikhail Kshevetskiy Reviewed-by: Simon Glass --- include/net/tcp.h | 179 ++++++++-- include/net/wget.h | 8 - net/fastboot_tcp.c | 190 +++++----- net/net.c | 4 + net/tcp.c | 845 ++++++++++++++++++++++++++++++++++----------- net/wget.c | 460 +++++++----------------- 6 files changed, 1008 insertions(+), 678 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index 0694af9d5b1..0b18475645d 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -265,6 +265,7 @@ union tcp_build_pkt { * @TCP_CLOSING: Rec FIN, sent FIN, ACK waiting for ACK * @TCP_FIN_WAIT_1: Sent FIN waiting for response * @TCP_FIN_WAIT_2: Rec ACK from FIN sent, waiting for FIN + * @TCP_LAST_ACK: Waiting for ACK of the connection termination */ enum tcp_state { TCP_CLOSED, @@ -274,7 +275,20 @@ enum tcp_state { TCP_CLOSE_WAIT, TCP_CLOSING, TCP_FIN_WAIT_1, - TCP_FIN_WAIT_2 + TCP_FIN_WAIT_2, + TCP_LAST_ACK, +}; + +/** + * enum tcp_status - TCP stream status for connection + * @TCP_ERR_OK: no rx/tx errors + * @TCP_ERR_TOUT: rx/tx timeout happened + * @TCP_ERR_RST: connection was reset + */ +enum tcp_status { + TCP_ERR_OK = 0, + TCP_ERR_TOUT, + TCP_ERR_RST, }; /** @@ -283,51 +297,150 @@ enum tcp_state { * @rport: Remote port, host byte order * @lport: Local port, host byte order * + * @priv: User private data (not used by tcp module) + * + * @max_retry_count: Maximum retransmit attempts (default 3) + * @initial_timeout: Timeout from initial TX to reTX (default 2 sec) + * @rx_inactiv_timeout: Maximum time from last rx till connection drop + * (default 30 sec) + * + * @on_closed: User callback, called just before destroying TCP stream + * @on_established: User callback, called when TCP stream enters + * TCP_ESTABLISHED state + * @on_rcv_nxt_update: User callback, called when all data in the segment + * [0..rx_bytes - 1] was received + * @on_snd_una_update: User callback, called when all data in the segment + * [0..tx_bytes - 1] were transferred and acknowledged + * @rx: User callback, called on receive of segment + * [rx_offs..rx_offs+len-1]. If NULL -- all incoming data + * will be ignored. User SHOULD store the segment and + * return the number of accepted bytes. + * WARNING: Previous segmengs may not be received yet + * @tx: User callback, called on transmit/retransmit of segment + * [tx_offs..tx_offs+maxlen-1]. If NULL -- no data will + * be transmitted. User SHOULD fill provided buffer and + * return the number of bytes in the buffer. + * WARNING: do not use tcp_stream_close() from this + * callback (it will break stream). Better use + * on_snd_una_update() callback for such purposes. + * + * @time_last_rx: Arrival time of last valid incoming package (ticks) + * @time_start: Timeout start time (ticks) + * @time_delta: Timeout duration (ticks) + * @time_handler Timeout handler for a stream + * * @state: TCP connection state + * @status: TCP stream status (OK or ERR) + * + * @fin_rx: Non-zero if TCP_FIN was received + * @fin_rx_seq: TCP sequence of rx FIN bit + * @fin_tx: Non-zero if TCP_FIN was sent (or planned to send) + * @fin_tx_seq: TCP sequence of tx FIN bit + * + * @iss: Initial send sequence number + * @snd_una: Send unacknowledged + * @snd_nxt: Send next + * @snd_wnd: Send window (in bytes) + * @snd_wl1: Segment sequence number used for last window update + * @snd_wl2: Segment acknowledgment number used for last window update * * @irs: Initial receive sequence number * @rcv_nxt: Receive next + * @rcv_wnd: Receive window (in bytes) * * @loc_timestamp: Local timestamp * @rmt_timestamp: Remote timestamp * + * @rmt_win_scale: Remote window scale factor + * * @lost: Used for SACK + * + * @retry_cnt: Number of retry attempts remaining. Only SYN, FIN + * or DATA segments are tried to retransmit. + * @retry_timeout: Current retry timeout (ms) + * @retry_action: TCP flags used for sending + * @retry_seq_num: TCP sequence for retransmit + * retry_tx_len: Number of data to transmit + * @retry_tx_offs: Position in the TX stream */ struct tcp_stream { struct in_addr rhost; u16 rport; u16 lport; - /* TCP connection state */ + void *priv; + + int max_retry_count; + int initial_timeout; + int rx_inactiv_timeout; + + void (*on_closed)(struct tcp_stream *tcp); + void (*on_established)(struct tcp_stream *tcp); + void (*on_rcv_nxt_update)(struct tcp_stream *tcp, u32 rx_bytes); + void (*on_snd_una_update)(struct tcp_stream *tcp, u32 tx_bytes); + u32 (*rx)(struct tcp_stream *tcp, u32 rx_offs, void *buf, u32 len); + u32 (*tx)(struct tcp_stream *tcp, u32 tx_offs, void *buf, u32 maxlen); + + ulong time_last_rx; + ulong time_start; + ulong time_delta; + void (*time_handler)(struct tcp_stream *tcp); + enum tcp_state state; + enum tcp_status status; + + int fin_rx; + u32 fin_rx_seq; + + int fin_tx; + u32 fin_tx_seq; + + u32 iss; + u32 snd_una; + u32 snd_nxt; + u32 snd_wnd; + u32 snd_wl1; + u32 snd_wl2; u32 irs; u32 rcv_nxt; + u32 rcv_wnd; /* TCP option timestamp */ u32 loc_timestamp; u32 rmt_timestamp; + /* TCP window scale */ + u8 rmt_win_scale; + /* TCP sliding window control used to request re-TX */ struct tcp_sack_v lost; + + /* used for data retransmission */ + int retry_cnt; + int retry_timeout; + u8 retry_action; + u32 retry_seq_num; + u32 retry_tx_len; + u32 retry_tx_offs; }; void tcp_init(void); -typedef int tcp_incoming_filter(struct in_addr rhost, - u16 rport, u16 sport); - /* - * This function sets user callback used to accept/drop incoming - * connections. Callback should: + * This function sets user callback called on TCP stream creation. + * Callback should: * + Check TCP stream endpoint and make connection verdict * - return non-zero value to accept connection * - return zero to drop connection + * + Setup TCP stream callbacks like: on_closed(), on_established(), + * n_rcv_nxt_update(), on_snd_una_update(), rx() and tx(). + * + Setup other stream related data * - * WARNING: If callback is NOT defined, all incoming connections - * will be dropped. + * WARNING: User MUST setup TCP stream on_create handler. Without it + * no connection (including outgoung) will be created. */ -void tcp_set_incoming_filter(tcp_incoming_filter *filter); +void tcp_stream_set_on_create_handler(int (*on_create)(struct tcp_stream *)); /* * tcp_stream_get -- Get or create TCP stream @@ -351,27 +464,37 @@ struct tcp_stream *tcp_stream_get(int is_new, struct in_addr rhost, */ struct tcp_stream *tcp_stream_connect(struct in_addr rhost, u16 rport); -enum tcp_state tcp_stream_get_state(struct tcp_stream *tcp); +/* + * tcp_stream_put -- Return stream to a TCP subsystem. Subsystem will + * check stream and destroy it (if stream was already + * closed). Otherwize no stream change will happen. + * @tcp: TCP stream to put + */ +void tcp_stream_put(struct tcp_stream *tcp); -int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int payload_len, - u8 action, u32 tcp_seq_num, u32 tcp_ack_num); +enum tcp_state tcp_stream_get_state(struct tcp_stream *tcp); +enum tcp_status tcp_stream_get_status(struct tcp_stream *tcp); -/** - * rxhand_tcp() - An incoming packet handler. - * @tcp: TCP stream - * @pkt: pointer to the application packet - * @dport: destination TCP port - * @sip: source IP address - * @sport: source TCP port - * @tcp_seq_num: TCP sequential number - * @tcp_ack_num: TCP acknowledgment number - * @action: TCP action (SYN, ACK, FIN, etc) - * @len: packet length + +/* + * tcp_stream_rx_offs(), + * tcp_stream_tx_offs() -- Returns offset of first unacknowledged byte + * in receive/transmit stream correspondingly. + * The result is NOT affected by sin/fin flags. + * @tcp: TCP stream */ -typedef void rxhand_tcp(struct tcp_stream *tcp, uchar *pkt, - u32 tcp_seq_num, u32 tcp_ack_num, - u8 action, unsigned int len); -void tcp_set_tcp_handler(rxhand_tcp *f); +u32 tcp_stream_rx_offs(struct tcp_stream *tcp); +u32 tcp_stream_tx_offs(struct tcp_stream *tcp); + +/* reset tcp stream */ +void tcp_stream_reset(struct tcp_stream *tcp); +/* force TCP stream closing, do NOT use from tcp->tx callback */ +void tcp_stream_close(struct tcp_stream *tcp); + +void tcp_streams_poll(void); + +int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int payload_len, + u8 action, u32 tcp_seq_num, u32 tcp_ack_num); void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int len); diff --git a/include/net/wget.h b/include/net/wget.h index 6714f7ea573..9a423b30414 100644 --- a/include/net/wget.h +++ b/include/net/wget.h @@ -8,14 +8,6 @@ */ void wget_start(void); -enum wget_state { - WGET_CLOSED, - WGET_CONNECTING, - WGET_CONNECTED, - WGET_TRANSFERRING, - WGET_TRANSFERRED -}; - #define DEBUG_WGET 0 /* Set to 1 for debug messages */ #define WGET_RETRY_COUNT 30 #define WGET_TIMEOUT 2000UL diff --git a/net/fastboot_tcp.c b/net/fastboot_tcp.c index 4d34fdc5a45..b6f7c417a21 100644 --- a/net/fastboot_tcp.c +++ b/net/fastboot_tcp.c @@ -10,140 +10,106 @@ #define FASTBOOT_TCP_PORT 5554 -static char command[FASTBOOT_COMMAND_LEN]; -static char response[FASTBOOT_RESPONSE_LEN]; - static const unsigned short handshake_length = 4; static const uchar *handshake = "FB01"; -static u32 curr_tcp_seq_num; -static u32 curr_tcp_ack_num; -static unsigned int curr_request_len; -static enum fastboot_tcp_state { - FASTBOOT_CLOSED, - FASTBOOT_CONNECTED, - FASTBOOT_DISCONNECTING -} state = FASTBOOT_CLOSED; - -static void fastboot_tcp_answer(struct tcp_stream *tcp, u8 action, - unsigned int len) -{ - const u32 response_seq_num = curr_tcp_ack_num; - const u32 response_ack_num = curr_tcp_seq_num + - (curr_request_len > 0 ? curr_request_len : 1); +static char rxbuf[sizeof(u64) + FASTBOOT_COMMAND_LEN + 1]; +static char txbuf[sizeof(u64) + FASTBOOT_RESPONSE_LEN + 1]; - net_send_tcp_packet(len, tcp->rhost, tcp->rport, tcp->lport, - action, response_seq_num, response_ack_num); -} +static u32 data_read; +static u32 tx_last_offs, tx_last_len; -static void fastboot_tcp_reset(struct tcp_stream *tcp) +static void tcp_stream_on_rcv_nxt_update(struct tcp_stream *tcp, u32 rx_bytes) { - fastboot_tcp_answer(tcp, TCP_RST, 0); - state = FASTBOOT_CLOSED; -} + u64 cmd_size; + __be64 len_be; + char saved; + int fastboot_command_id, len; + + if ((data_read == 0) && (rx_bytes >= handshake_length)) { + if (memcmp(rxbuf, handshake, handshake_length) != 0) { + printf("fastboot: bad handshake\n"); + tcp_stream_close(tcp); + return; + } -static void fastboot_tcp_send_packet(struct tcp_stream *tcp, u8 action, - const uchar *data, unsigned int len) -{ - uchar *pkt = net_get_async_tx_pkt_buf(); + tx_last_offs = 0; + tx_last_len = handshake_length; + memcpy(txbuf, handshake, handshake_length); + + data_read += handshake_length; + rx_bytes -= handshake_length; + if (rx_bytes > 0) + memmove(rxbuf, rxbuf + handshake_length, rx_bytes); + return; + } - memset(pkt, '\0', PKTSIZE); - pkt += net_eth_hdr_size() + IP_TCP_HDR_SIZE + TCP_TSOPT_SIZE + 2; - memcpy(pkt, data, len); - fastboot_tcp_answer(tcp, action, len); - memset(pkt, '\0', PKTSIZE); + if (rx_bytes < sizeof(u64)) + return; + + memcpy(&cmd_size, rxbuf, sizeof(u64)); + cmd_size = __be64_to_cpu(cmd_size); + if (rx_bytes < sizeof(u64) + cmd_size) + return; + + saved = rxbuf[sizeof(u64) + cmd_size]; + rxbuf[sizeof(u64) + cmd_size] = '\0'; + fastboot_command_id = fastboot_handle_command(rxbuf + sizeof(u64), + txbuf + sizeof(u64)); + fastboot_handle_boot(fastboot_command_id, + strncmp("OKAY", txbuf + sizeof(u64), 4) != 0); + rxbuf[sizeof(u64) + cmd_size] = saved; + + len = strlen(txbuf + sizeof(u64)); + len_be = __cpu_to_be64(len); + memcpy(txbuf, &len_be, sizeof(u64)); + + tx_last_offs += tx_last_len; + tx_last_len = len + sizeof(u64); + + data_read += sizeof(u64) + cmd_size; + rx_bytes -= sizeof(u64) + cmd_size; + if (rx_bytes > 0) + memmove(rxbuf, rxbuf + sizeof(u64) + cmd_size, rx_bytes); } -static void fastboot_tcp_send_message(struct tcp_stream *tcp, - const char *message, unsigned int len) +static u32 tcp_stream_rx(struct tcp_stream *tcp, u32 rx_offs, void *buf, u32 len) { - __be64 len_be = __cpu_to_be64(len); - uchar *pkt = net_get_async_tx_pkt_buf(); - - memset(pkt, '\0', PKTSIZE); - pkt += net_eth_hdr_size() + IP_TCP_HDR_SIZE + TCP_TSOPT_SIZE + 2; - // Put first 8 bytes as a big endian message length - memcpy(pkt, &len_be, 8); - pkt += 8; - memcpy(pkt, message, len); - fastboot_tcp_answer(tcp, TCP_ACK | TCP_PUSH, len + 8); - memset(pkt, '\0', PKTSIZE); + memcpy(rxbuf + rx_offs - data_read, buf, len); + return len; } -static void fastboot_tcp_handler_ipv4(struct tcp_stream *tcp, uchar *pkt, - u32 tcp_seq_num, u32 tcp_ack_num, - u8 action, unsigned int len) +static u32 tcp_stream_tx(struct tcp_stream *tcp, u32 tx_offs, void *buf, u32 maxlen) { - int fastboot_command_id; - u64 command_size; - u8 tcp_fin = action & TCP_FIN; - u8 tcp_push = action & TCP_PUSH; - - curr_tcp_seq_num = tcp_seq_num; - curr_tcp_ack_num = tcp_ack_num; - curr_request_len = len; - - switch (state) { - case FASTBOOT_CLOSED: - if (tcp_push) { - if (len != handshake_length || - strlen(pkt) != handshake_length || - memcmp(pkt, handshake, handshake_length) != 0) { - fastboot_tcp_reset(tcp); - break; - } - fastboot_tcp_send_packet(tcp, TCP_ACK | TCP_PUSH, - handshake, handshake_length); - state = FASTBOOT_CONNECTED; - } - break; - case FASTBOOT_CONNECTED: - if (tcp_fin) { - fastboot_tcp_answer(tcp, TCP_FIN | TCP_ACK, 0); - state = FASTBOOT_DISCONNECTING; - break; - } - if (tcp_push) { - // First 8 bytes is big endian message length - command_size = __be64_to_cpu(*(u64 *)pkt); - len -= 8; - pkt += 8; - - // Only single packet messages are supported ATM - if (strlen(pkt) != command_size) { - fastboot_tcp_reset(tcp); - break; - } - strlcpy(command, pkt, len + 1); - fastboot_command_id = fastboot_handle_command(command, response); - fastboot_tcp_send_message(tcp, response, strlen(response)); - fastboot_handle_boot(fastboot_command_id, - strncmp("OKAY", response, 4) == 0); - } - break; - case FASTBOOT_DISCONNECTING: - if (tcp_push) - state = FASTBOOT_CLOSED; - break; - } + /* by design: tx_offs >= tx_last_offs */ + if (tx_offs >= tx_last_offs + tx_last_len) + return 0; - memset(command, 0, FASTBOOT_COMMAND_LEN); - memset(response, 0, FASTBOOT_RESPONSE_LEN); - curr_tcp_seq_num = 0; - curr_tcp_ack_num = 0; - curr_request_len = 0; + maxlen = tx_last_offs + tx_last_len - tx_offs; + memcpy(buf, txbuf + (tx_offs - tx_last_offs), maxlen); + return maxlen; } -static int incoming_filter(struct in_addr rhost, u16 rport, u16 lport) +static int tcp_stream_on_create(struct tcp_stream *tcp) { - return (lport == FASTBOOT_TCP_PORT); + if (tcp->lport != FASTBOOT_TCP_PORT) + return 0; + + data_read = 0; + tx_last_offs = 0; + tx_last_len = 0; + + tcp->on_rcv_nxt_update = tcp_stream_on_rcv_nxt_update; + tcp->rx = tcp_stream_rx; + tcp->tx = tcp_stream_tx; + return 1; } void fastboot_tcp_start_server(void) { + memset(net_server_ethaddr, 0, 6); + tcp_stream_set_on_create_handler(tcp_stream_on_create); + printf("Using %s device\n", eth_get_name()); printf("Listening for fastboot command on tcp %pI4\n", &net_ip); - - tcp_set_incoming_filter(incoming_filter); - tcp_set_tcp_handler(fastboot_tcp_handler_ipv4); } diff --git a/net/net.c b/net/net.c index b33ea59a9fa..86182cc504e 100644 --- a/net/net.c +++ b/net/net.c @@ -646,6 +646,9 @@ restart: * errors that may have happened. */ eth_rx(); +#if defined(CONFIG_PROT_TCP) + tcp_streams_poll(); +#endif /* * Abort if ctrl-c was pressed. @@ -952,6 +955,7 @@ int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport, + tcp_set_tcp_header(tcp, pkt + eth_hdr_size, payload_len, action, tcp_seq_num, tcp_ack_num); + tcp_stream_put(tcp); break; #endif default: diff --git a/net/tcp.c b/net/tcp.c index 7e445eaffd6..37dda6f84f9 100644 --- a/net/tcp.c +++ b/net/tcp.c @@ -24,9 +24,26 @@ #include #include -static int tcp_activity_count; +/* + * The start sequence number increment for the two sequently created + * connections within the same timer tick. This number must be: + * - prime (to increase the time before the same number will be generated) + * - larger than typical MTU (to avoid similar numbers for two sequently + * created connections) + */ +#define TCP_START_SEQ_INC 2153 /* just large prime number */ + +#define TCP_SEND_RETRY 3 +#define TCP_SEND_TIMEOUT 2000UL +#define TCP_RX_INACTIVE_TIMEOUT 30000UL +#define TCP_RCV_WND_SIZE (PKTBUFSRX * TCP_MSS) + +#define TCP_PACKET_OK 0 +#define TCP_PACKET_DROP 1 + static struct tcp_stream tcp_stream; -static tcp_incoming_filter *incoming_filter; + +static int (*tcp_stream_on_create)(struct tcp_stream *tcp); /* * TCP lengths are stored as a rounded up number of 32 bit words. @@ -35,12 +52,10 @@ static tcp_incoming_filter *incoming_filter; */ #define LEN_B_TO_DW(x) ((x) >> 2) #define ROUND_TCPHDR_LEN(x) (LEN_B_TO_DW((x) + 3)) +#define ROUND_TCPHDR_BYTES(x) (((x) + 3) & ~3) #define SHIFT_TO_TCPHDRLEN_FIELD(x) ((x) << 4) #define GET_TCP_HDR_LEN_IN_BYTES(x) ((x) >> 2) -/* Current TCP RX packet handler */ -static rxhand_tcp *tcp_packet_handler; - #define RANDOM_PORT_START 1024 #define RANDOM_PORT_RANGE 0x4000 @@ -62,6 +77,21 @@ static inline s32 tcp_seq_cmp(u32 a, u32 b) return (s32)(a - b); } +static inline u32 tcp_get_start_seq(void) +{ + static u32 tcp_seq_inc; + u32 tcp_seq; + + tcp_seq = (get_timer(0) & 0xffffffff) + tcp_seq_inc; + tcp_seq_inc += TCP_START_SEQ_INC; + return tcp_seq; +} + +static inline ulong msec_to_ticks(ulong msec) +{ + return msec * CONFIG_SYS_HZ / 1000; +} + /** * tcp_stream_get_state() - get TCP stream state * @tcp: tcp stream @@ -84,15 +114,70 @@ static void tcp_stream_set_state(struct tcp_stream *tcp, tcp->state = new_state; } +/** + * tcp_stream_get_status() - get TCP stream status + * @tcp: tcp stream + * + * Return: TCP stream status + */ +enum tcp_status tcp_stream_get_status(struct tcp_stream *tcp) +{ + return tcp->status; +} + +/** + * tcp_stream_set_status() - set TCP stream state + * @tcp: tcp stream + * @new_satus: new TCP stream status + */ +static void tcp_stream_set_status(struct tcp_stream *tcp, + enum tcp_state new_status) +{ + tcp->status = new_status; +} + +static void tcp_stream_init(struct tcp_stream *tcp, + struct in_addr rhost, u16 rport, u16 lport) +{ + memset(tcp, 0, sizeof(struct tcp_stream)); + tcp->rhost.s_addr = rhost.s_addr; + tcp->rport = rport; + tcp->lport = lport; + tcp->state = TCP_CLOSED; + tcp->lost.len = TCP_OPT_LEN_2; + tcp->rcv_wnd = TCP_RCV_WND_SIZE; + tcp->max_retry_count = TCP_SEND_RETRY; + tcp->initial_timeout = TCP_SEND_TIMEOUT; + tcp->rx_inactiv_timeout = TCP_RX_INACTIVE_TIMEOUT; + tcp->time_last_rx = get_timer(0); +} + +static void tcp_stream_destroy(struct tcp_stream *tcp) +{ + if (tcp->on_closed != NULL) + tcp->on_closed(tcp); + memset(tcp, 0, sizeof(struct tcp_stream)); +} + void tcp_init(void) { - incoming_filter = NULL; - tcp_stream.state = TCP_CLOSED; + static int initialized; + struct tcp_stream *tcp = &tcp_stream; + + tcp_stream_on_create = NULL; + if (!initialized) { + initialized = 1; + memset(tcp, 0, sizeof(struct tcp_stream)); + } + + tcp_stream_set_state(tcp, TCP_CLOSED); + tcp_stream_set_status(tcp, TCP_ERR_RST); + tcp_stream_destroy(tcp); } -void tcp_set_incoming_filter(tcp_incoming_filter *filter) +void tcp_stream_set_on_create_handler(int (*on_create)(struct tcp_stream *)) { - incoming_filter = filter; + tcp_stream_on_create = on_create; } static struct tcp_stream *tcp_stream_add(struct in_addr rhost, @@ -100,15 +185,14 @@ static struct tcp_stream *tcp_stream_add(struct in_addr rhost, { struct tcp_stream *tcp = &tcp_stream; - if (tcp->state != TCP_CLOSED) + if ((tcp_stream_on_create == NULL) || + (tcp->state != TCP_CLOSED)) + return NULL; + + tcp_stream_init(tcp, rhost, rport, lport); + if (!tcp_stream_on_create(tcp)) return NULL; - memset(tcp, 0, sizeof(struct tcp_stream)); - tcp->rhost.s_addr = rhost.s_addr; - tcp->rport = rport; - tcp->lport = lport; - tcp->state = TCP_CLOSED; - tcp->lost.len = TCP_OPT_LEN_2; return tcp; } @@ -122,30 +206,203 @@ struct tcp_stream *tcp_stream_get(int is_new, struct in_addr rhost, tcp->lport == lport) return tcp; - if (!is_new || !incoming_filter) || - !incoming_filter(rhost, rport, lport)) - return NULL; + return is_new ? tcp_stream_add(rhost, rport, lport) : NULL; +} - return tcp_stream_add(rhost, rport, lport); +void tcp_stream_put(struct tcp_stream *tcp) +{ + if (tcp->state == TCP_CLOSED) + tcp_stream_destroy(tcp); } -static void dummy_handler(struct tcp_stream *tcp, uchar *pkt, - u32 tcp_seq_num, u32 tcp_ack_num, - u8 action, unsigned int len) +u32 tcp_stream_rx_offs(struct tcp_stream *tcp) { + u32 ret; + + switch (tcp->state) { + case TCP_CLOSED: + case TCP_SYN_SENT: + case TCP_SYN_RECEIVED: + return 0; + default: + break; + } + + ret = tcp->rcv_nxt - tcp->irs - 1; + if (tcp->fin_rx && (tcp->rcv_nxt == tcp->fin_rx_seq)) + ret--; + return ret; } -/** - * tcp_set_tcp_handler() - set a handler to receive data - * @f: handler - */ -void tcp_set_tcp_handler(rxhand_tcp *f) +u32 tcp_stream_tx_offs(struct tcp_stream *tcp) +{ + u32 ret; + + switch (tcp->state) { + case TCP_CLOSED: + case TCP_SYN_SENT: + case TCP_SYN_RECEIVED: + return 0; + default: + break; + } + + ret = tcp->snd_una - tcp->iss - 1; + if (tcp->fin_tx && (tcp->snd_una == tcp->fin_tx_seq + 1)) + ret--; + return ret; +} + +static void tcp_stream_set_time_handler(struct tcp_stream *tcp, ulong msec, + void (*handler)(struct tcp_stream *)) +{ + if (msec == 0) { + tcp->time_handler = NULL; + return; + } + + tcp->time_handler = handler; + tcp->time_start = get_timer(0); + tcp->time_delta = msec_to_ticks(msec); +} + +static void tcp_send_packet(struct tcp_stream *tcp, u8 action, + u32 tcp_seq_num, u32 tcp_ack_num, u32 tx_len) +{ + net_send_tcp_packet(tx_len, tcp->rhost, tcp->rport, + tcp->lport, action, tcp_seq_num, + tcp_ack_num); +} + +static void tcp_send_repeat(struct tcp_stream *tcp) +{ + uchar *ptr; + u32 tcp_opts_size; + + if (tcp->retry_cnt == 0) { + puts("\nTCP: send retry counter exceeded\n"); + tcp_send_packet(tcp, TCP_RST, tcp->retry_seq_num, + tcp->rcv_nxt, 0); + tcp_stream_set_status(tcp, TCP_ERR_TOUT); + tcp_stream_set_state(tcp, TCP_CLOSED); + tcp_stream_destroy(tcp); + return; + } + tcp->retry_cnt--; + tcp->retry_timeout += tcp->initial_timeout; + + if (tcp->retry_tx_len > 0) { + tcp_opts_size = ROUND_TCPHDR_BYTES(TCP_TSOPT_SIZE + + tcp->lost.len); + ptr = net_tx_packet + net_eth_hdr_size() + + IP_TCP_HDR_SIZE + tcp_opts_size; + + if (tcp->retry_tx_len > TCP_MSS - tcp_opts_size) + tcp->retry_tx_len = TCP_MSS - tcp_opts_size; + + /* refill packet data */ + tcp->tx(tcp, tcp->retry_tx_offs, ptr, tcp->retry_tx_len); + } + tcp_send_packet(tcp, tcp->retry_action, tcp->retry_seq_num, + tcp->rcv_nxt, tcp->retry_tx_len); + + tcp_stream_set_time_handler(tcp, tcp->retry_timeout, tcp_send_repeat); +} + +static void tcp_send_packet_with_retry(struct tcp_stream *tcp, u8 action, + u32 tcp_seq_num, u32 tx_len, u32 tx_offs) { - debug_cond(DEBUG_INT_STATE, "--- net_loop TCP handler set (%p)\n", f); - if (!f) - tcp_packet_handler = dummy_handler; - else - tcp_packet_handler = f; + tcp->retry_cnt = tcp->max_retry_count; + tcp->retry_timeout = tcp->initial_timeout; + tcp->retry_action = action; + tcp->retry_seq_num = tcp_seq_num; + tcp->retry_tx_len = tx_len; + tcp->retry_tx_offs = tx_offs; + + tcp_send_packet(tcp, action, tcp_seq_num, tcp->rcv_nxt, tx_len); + tcp_stream_set_time_handler(tcp, tcp->retry_timeout, tcp_send_repeat); +} + +static inline u8 tcp_stream_fin_needed(struct tcp_stream *tcp, u32 tcp_seq_num) +{ + return (tcp->fin_tx && (tcp_seq_num == tcp->fin_tx_seq)) ? TCP_FIN : 0; +} + +static void tcp_steam_tx_try(struct tcp_stream *tcp) +{ + uchar *ptr; + u32 tx_offs, tx_len, tcp_opts_size; + + if ((tcp->state != TCP_ESTABLISHED) || + (tcp->time_handler != NULL) || + (tcp->tx == NULL)) + return; + + tcp_opts_size = ROUND_TCPHDR_BYTES(TCP_TSOPT_SIZE + tcp->lost.len); + tx_len = TCP_MSS - tcp_opts_size; + if (tcp->fin_tx) { + /* do not try to send beyonds FIN packet limits */ + if (tcp_seq_cmp(tcp->snd_una, tcp->fin_tx_seq) >= 0) + return; + + tx_len = tcp->fin_tx_seq - tcp->snd_una; + if (tx_len > TCP_MSS - tcp_opts_size) + tx_len = TCP_MSS - tcp_opts_size; + } + + tx_offs = tcp_stream_tx_offs(tcp); + ptr = net_tx_packet + net_eth_hdr_size() + + IP_TCP_HDR_SIZE + tcp_opts_size; + + /* fill packet data and adjust size */ + tx_len = tcp->tx(tcp, tx_offs, ptr, tx_len); + if (tx_len == 0) + return; + + if (tcp_seq_cmp(tcp->snd_una + tx_len, tcp->snd_nxt) > 0) + tcp->snd_nxt = tcp->snd_una + tx_len; + + tcp_send_packet_with_retry(tcp, TCP_ACK | TCP_PUSH, + tcp->snd_una, tx_len, tx_offs); +} + +static void tcp_stream_poll(struct tcp_stream *tcp, ulong time) +{ + ulong delta; + void (*handler)(struct tcp_stream *tcp); + + if (tcp->state == TCP_CLOSED) + return; + + /* handle rx inactivity timeout */ + delta = msec_to_ticks(tcp->rx_inactiv_timeout); + if (time - tcp->time_last_rx >= delta) { + puts("\nTCP: rx inactivity timeout exceeded\n"); + tcp_stream_reset(tcp); + tcp_stream_set_status(tcp, TCP_ERR_TOUT); + tcp_stream_destroy(tcp); + return; + } + + /* handle retransmit timeout */ + if ((tcp->time_handler != NULL) && + (time - tcp->time_start >= tcp->time_delta)) { + handler = tcp->time_handler; + tcp->time_handler = NULL; + handler(tcp); + } + + tcp_steam_tx_try(tcp); +} + +void tcp_streams_poll(void) +{ + ulong time; + struct tcp_stream *tcp; + + time = get_timer(0); + tcp = &tcp_stream; + tcp_stream_poll(tcp, time); } /** @@ -300,18 +557,8 @@ int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int payload_len, "TCP Hdr:SYN (%pI4, %pI4, sq=%u, ak=%u)\n", &tcp->rhost, &net_ip, tcp_seq_num, tcp_ack_num); - tcp_activity_count = 0; net_set_syn_options(tcp, b); - tcp_seq_num = 0; - tcp_ack_num = 0; pkt_hdr_len = IP_TCP_O_SIZE; - if (tcp->state == TCP_SYN_SENT) { /* Too many SYNs */ - action = TCP_FIN; - tcp->state = TCP_FIN_WAIT_1; - } else { - tcp->lost.len = TCP_OPT_LEN_2; - tcp->state = TCP_SYN_SENT; - } break; case TCP_SYN | TCP_ACK: case TCP_ACK: @@ -328,21 +575,16 @@ int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int payload_len, &tcp->rhost, &net_ip, tcp_seq_num, tcp_ack_num); payload_len = 0; pkt_hdr_len = IP_TCP_HDR_SIZE; - tcp->state = TCP_FIN_WAIT_1; break; case TCP_RST | TCP_ACK: case TCP_RST: debug_cond(DEBUG_DEV_PKT, "TCP Hdr:RST (%pI4, %pI4, s=%u, a=%u)\n", &tcp->rhost, &net_ip, tcp_seq_num, tcp_ack_num); - tcp->state = TCP_CLOSED; break; /* Notify connection closing */ case (TCP_FIN | TCP_ACK): case (TCP_FIN | TCP_ACK | TCP_PUSH): - if (tcp->state == TCP_CLOSE_WAIT) - tcp->state = TCP_CLOSING; - debug_cond(DEBUG_DEV_PKT, "TCP Hdr:FIN ACK PSH(%pI4, %pI4, s=%u, a=%u, A=%x)\n", &tcp->rhost, &net_ip, @@ -382,7 +624,7 @@ int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int payload_len, * it is, then the u-boot tftp or nfs kernel netboot should be * considered. */ - b->ip.hdr.tcp_win = htons(PKTBUFSRX * TCP_MSS >> TCP_SCALE); + b->ip.hdr.tcp_win = htons(tcp->rcv_wnd >> TCP_SCALE); b->ip.hdr.tcp_xsum = 0; b->ip.hdr.tcp_ugr = 0; @@ -501,6 +743,7 @@ void tcp_hole(struct tcp_stream *tcp, u32 tcp_seq_num, u32 len) void tcp_parse_options(struct tcp_stream *tcp, uchar *o, int o_len) { struct tcp_t_opt *tsopt; + struct tcp_scale *wsopt; uchar *p = o; /* @@ -515,10 +758,13 @@ void tcp_parse_options(struct tcp_stream *tcp, uchar *o, int o_len) case TCP_O_END: return; case TCP_O_MSS: - case TCP_O_SCL: case TCP_P_SACK: case TCP_V_SACK: break; + case TCP_O_SCL: + wsopt = (struct tcp_scale *)p; + tcp->rmt_win_scale = wsopt->scale; + break; case TCP_O_TS: tsopt = (struct tcp_t_opt *)p; tcp->rmt_timestamp = tsopt->t_snd; @@ -533,129 +779,330 @@ void tcp_parse_options(struct tcp_stream *tcp, uchar *o, int o_len) } } -static u8 tcp_state_machine(struct tcp_stream *tcp, u8 tcp_flags, - u32 tcp_seq_num, int payload_len) +static int tcp_seg_in_wnd(struct tcp_stream *tcp, + u32 tcp_seq_num, int payload_len) +{ + if ((payload_len == 0) && (tcp->rcv_wnd == 0)) { + if (tcp_seq_num == tcp->rcv_nxt) + return 1; + } + if ((payload_len == 0) && (tcp->rcv_wnd > 0)) { + if ((tcp_seq_cmp(tcp->rcv_nxt, tcp_seq_num) <= 0) && + (tcp_seq_cmp(tcp_seq_num, tcp->rcv_nxt + tcp->rcv_wnd) < 0)) + return 1; + } + if ((payload_len > 0) && (tcp->rcv_wnd > 0)) { + if ((tcp_seq_cmp(tcp->rcv_nxt, tcp_seq_num) <= 0) && + (tcp_seq_cmp(tcp_seq_num, tcp->rcv_nxt + tcp->rcv_wnd) < 0)) + return 1; + tcp_seq_num += payload_len - 1; + if ((tcp_seq_cmp(tcp->rcv_nxt, tcp_seq_num) <= 0) && + (tcp_seq_cmp(tcp_seq_num, tcp->rcv_nxt + tcp->rcv_wnd) < 0)) + return 1; + } + return 0; +} + +static int tcp_rx_check_ack_num(struct tcp_stream *tcp, u32 tcp_seq_num, + u32 tcp_ack_num, u32 tcp_win_size) +{ + u32 old_offs, new_offs; + u8 action; + + switch (tcp->state) { + case TCP_SYN_RECEIVED: + if ((tcp_seq_cmp(tcp->snd_una, tcp_ack_num) >= 0) || + (tcp_seq_cmp(tcp_ack_num, tcp->snd_nxt) > 0)) { + // segment acknowledgment is not acceptable + tcp_send_packet(tcp, TCP_RST, tcp_ack_num, 0, 0); + return TCP_PACKET_DROP; + } + + tcp_stream_set_state(tcp, TCP_ESTABLISHED); + tcp->snd_wnd = tcp_win_size; + tcp->snd_wl1 = tcp_seq_num; + tcp->snd_wl2 = tcp_ack_num; + + if (tcp->on_established != NULL) + tcp->on_established(tcp); + + fallthrough; + + case TCP_ESTABLISHED: + case TCP_FIN_WAIT_1: + case TCP_FIN_WAIT_2: + case TCP_CLOSE_WAIT: + case TCP_CLOSING: + if (tcp_seq_cmp(tcp_ack_num, tcp->snd_nxt) > 0) { + // ACK acks something not yet sent + action = tcp_stream_fin_needed(tcp, tcp->snd_una) | TCP_ACK; + tcp_send_packet(tcp, action, tcp->snd_una, tcp->rcv_nxt, 0); + return TCP_PACKET_DROP; + } + + if (tcp_seq_cmp(tcp->snd_una, tcp_ack_num) < 0) { + old_offs = tcp_stream_tx_offs(tcp); + tcp->snd_una = tcp_ack_num; + new_offs = tcp_stream_tx_offs(tcp); + if ((tcp->time_handler != NULL) && + (tcp_seq_cmp(tcp->snd_una, tcp->retry_seq_num) > 0)) { + tcp_stream_set_time_handler(tcp, 0, NULL); + } + if ((tcp->on_snd_una_update != NULL) && + (old_offs != new_offs)) + tcp->on_snd_una_update(tcp, new_offs); + } + + if (tcp_seq_cmp(tcp->snd_una, tcp_ack_num) <= 0) { + if ((tcp_seq_cmp(tcp->snd_wl1, tcp_seq_num) < 0) || + ((tcp->snd_wl1 == tcp_seq_num) && + (tcp_seq_cmp(tcp->snd_wl2, tcp_seq_num) <= 0))) { + tcp->snd_wnd = tcp_win_size; + tcp->snd_wl1 = tcp_seq_num; + tcp->snd_wl2 = tcp_ack_num; + } + } + + if (tcp->state == TCP_FIN_WAIT_1) { + if (tcp->snd_una == tcp->snd_nxt) + tcp_stream_set_state(tcp, TCP_FIN_WAIT_2); + } + + if (tcp->state == TCP_CLOSING) { + if (tcp->snd_una == tcp->snd_nxt) + tcp_stream_set_state(tcp, TCP_CLOSED); + } + return TCP_PACKET_OK; + + case TCP_LAST_ACK: + if (tcp_ack_num == tcp->snd_nxt) + tcp_stream_set_state(tcp, TCP_CLOSED); + return TCP_PACKET_OK; + + default: + return TCP_PACKET_DROP; + } +} + +static int tcp_rx_user_data(struct tcp_stream *tcp, u32 tcp_seq_num, + char *buf, int len) { - u8 tcp_fin = tcp_flags & TCP_FIN; - u8 tcp_syn = tcp_flags & TCP_SYN; - u8 tcp_rst = tcp_flags & TCP_RST; - u8 tcp_push = tcp_flags & TCP_PUSH; - u8 tcp_ack = tcp_flags & TCP_ACK; - u8 action = TCP_DATA; + u32 tmp_len, buf_offs, old_offs, new_offs; + u8 action; + if (len == 0) + return TCP_PACKET_OK; + + switch (tcp->state) { + case TCP_ESTABLISHED: + case TCP_FIN_WAIT_1: + case TCP_FIN_WAIT_2: + break; + default: + return TCP_PACKET_DROP; + } + + tmp_len = len; + old_offs = tcp_stream_rx_offs(tcp); + buf_offs = tcp_seq_num - tcp->irs - 1; + if (tcp->rx != NULL) + tmp_len = tcp->rx(tcp, buf_offs, buf, len); + if (tmp_len) + tcp_hole(tcp, tcp_seq_num, tmp_len); + + new_offs = tcp_stream_rx_offs(tcp); + if ((tcp->on_rcv_nxt_update != NULL) && (old_offs != new_offs)) + tcp->on_rcv_nxt_update(tcp, new_offs); + + action = tcp_stream_fin_needed(tcp, tcp->snd_una) | TCP_ACK; + tcp_send_packet(tcp, action, tcp->snd_una, tcp->rcv_nxt, 0); + return TCP_PACKET_OK; +} + +void tcp_rx_state_machine(struct tcp_stream *tcp, + union tcp_build_pkt *b, unsigned int pkt_len) +{ + int tcp_len = pkt_len - IP_HDR_SIZE; + u32 tcp_seq_num, tcp_ack_num, tcp_win_size; + int tcp_hdr_len, payload_len; + u8 tcp_flags, action; + + tcp_hdr_len = GET_TCP_HDR_LEN_IN_BYTES(b->ip.hdr.tcp_hlen); + payload_len = tcp_len - tcp_hdr_len; + + if (tcp_hdr_len > TCP_HDR_SIZE) + tcp_parse_options(tcp, (uchar *)b + IP_TCP_HDR_SIZE, + tcp_hdr_len - TCP_HDR_SIZE); /* - * tcp_flags are examined to determine TX action in a given state - * tcp_push is interpreted to mean "inform the app" - * urg, ece, cer and nonce flags are not supported. - * - * exe and crw are use to signal and confirm knowledge of congestion. - * This TCP only sends a file request and acks. If it generates - * congestion, the network is broken. + * Incoming sequence and ack numbers are server's view of the numbers. + * The app must swap the numbers when responding. */ - debug_cond(DEBUG_INT_STATE, "TCP STATE ENTRY %x\n", action); - if (tcp_rst) { - action = TCP_DATA; - tcp->state = TCP_CLOSED; - net_set_state(NETLOOP_FAIL); - debug_cond(DEBUG_INT_STATE, "TCP Reset %x\n", tcp_flags); - return TCP_RST; - } + tcp_seq_num = ntohl(b->ip.hdr.tcp_seq); + tcp_ack_num = ntohl(b->ip.hdr.tcp_ack); + tcp_win_size = ntohs(b->ip.hdr.tcp_win) << tcp->rmt_win_scale; + + tcp_flags = b->ip.hdr.tcp_flags; - switch (tcp->state) { +// printf("pkt: seq=%d, ack=%d, flags=%x, len=%d\n", +// tcp_seq_num - tcp->irs, tcp_ack_num - tcp->iss, tcp_flags, pkt_len); +// printf("tcp: rcv_nxt=%d, snd_una=%d, snd_nxt=%d\n\n", +// tcp->rcv_nxt - tcp->irs, tcp->snd_una - tcp->iss, tcp->snd_nxt - tcp->iss); + + switch (tcp->state) { case TCP_CLOSED: - debug_cond(DEBUG_INT_STATE, "TCP CLOSED %x\n", tcp_flags); - if (tcp_syn) { - action = TCP_SYN | TCP_ACK; - tcp->irs = tcp_seq_num; - tcp->rcv_nxt = tcp_seq_num + 1; - tcp->lost.len = TCP_OPT_LEN_2; - tcp->state = TCP_SYN_RECEIVED; - } else if (tcp_ack || tcp_fin) { - action = TCP_DATA; + if (tcp_flags & TCP_RST) + return; + + if (tcp_flags & TCP_ACK) { + tcp_send_packet(tcp, TCP_RST, tcp_ack_num, 0, 0); + return; } - break; - case TCP_SYN_RECEIVED: + + if (!(tcp_flags & TCP_SYN)) + return; + + tcp->irs = tcp_seq_num; + tcp->rcv_nxt = tcp->irs + 1; + + tcp->iss = tcp_get_start_seq(); + tcp->snd_una = tcp->iss; + tcp->snd_nxt = tcp->iss + 1; + tcp->snd_wnd = tcp_win_size; + + tcp->time_last_rx = get_timer(0); + + tcp_stream_set_state(tcp, TCP_SYN_RECEIVED); + tcp_send_packet_with_retry(tcp, TCP_SYN | TCP_ACK, + tcp->iss, 0, 0); + return; + case TCP_SYN_SENT: - debug_cond(DEBUG_INT_STATE, "TCP_SYN_SENT | TCP_SYN_RECEIVED %x, %u\n", - tcp_flags, tcp_seq_num); - if (tcp_fin) { - action = action | TCP_PUSH; - tcp->state = TCP_CLOSE_WAIT; - } else if (tcp_ack || (tcp_syn && tcp_ack)) { - action |= TCP_ACK; - tcp->irs = tcp_seq_num; - tcp->rcv_nxt = tcp_seq_num + 1; - tcp->state = TCP_ESTABLISHED; - - if (tcp_syn && tcp_ack) - action |= TCP_PUSH; - } else { - action = TCP_DATA; + if (!(tcp_flags & TCP_ACK)) + return; + + if ((tcp_seq_cmp(tcp_ack_num, tcp->iss) <= 0) || + (tcp_seq_cmp(tcp_ack_num, tcp->snd_nxt) > 0)) { + if (!(tcp_flags & TCP_RST)) + tcp_send_packet(tcp, TCP_RST, tcp_ack_num, 0, 0); + return; } - break; + + if (tcp_flags & TCP_RST) { + tcp_stream_set_status(tcp, TCP_ERR_RST); + tcp_stream_set_state(tcp, TCP_CLOSED); + return; + } + + if (!(tcp_flags & TCP_SYN)) + return; + + /* stop retransmit of SYN */ + tcp_stream_set_time_handler(tcp, 0, NULL); + + tcp->irs = tcp_seq_num; + tcp->rcv_nxt = tcp->irs + 1; + tcp->snd_una = tcp_ack_num; + + tcp->time_last_rx = get_timer(0); + + /* our SYN has been ACKed */ + tcp_stream_set_state(tcp, TCP_ESTABLISHED); + + if (tcp->on_established != NULL) + tcp->on_established(tcp); + + action = tcp_stream_fin_needed(tcp, tcp->snd_una) | TCP_ACK; + tcp_send_packet(tcp, action, tcp->snd_una, tcp->rcv_nxt, 0); + tcp_rx_user_data(tcp, tcp_seq_num, + ((char *)b) + pkt_len - payload_len, + payload_len); + return; + + case TCP_SYN_RECEIVED: case TCP_ESTABLISHED: - debug_cond(DEBUG_INT_STATE, "TCP_ESTABLISHED %x\n", tcp_flags); - if (payload_len > 0) { - tcp_hole(tcp, tcp_seq_num, payload_len); - tcp_fin = TCP_DATA; /* cause standalone FIN */ + case TCP_FIN_WAIT_1: + case TCP_FIN_WAIT_2: + case TCP_CLOSE_WAIT: + case TCP_CLOSING: + case TCP_LAST_ACK: + if (!tcp_seg_in_wnd(tcp, tcp_seq_num, payload_len)) { + if (tcp_flags & TCP_RST) + return; + action = tcp_stream_fin_needed(tcp, tcp->snd_una) | TCP_ACK; + tcp_send_packet(tcp, action, tcp->snd_una, tcp->rcv_nxt, 0); + return; } - if ((tcp_fin) && - (!IS_ENABLED(CONFIG_PROT_TCP_SACK) || - tcp->lost.len <= TCP_OPT_LEN_2)) { - action = action | TCP_FIN | TCP_PUSH | TCP_ACK; - tcp->state = TCP_CLOSE_WAIT; - } else if (tcp_ack) { - action = TCP_DATA; + tcp->time_last_rx = get_timer(0); + + if (tcp_flags & TCP_RST) { + tcp_stream_set_status(tcp, TCP_ERR_RST); + tcp_stream_set_state(tcp, TCP_CLOSED); + return; } - if (tcp_syn) - action = TCP_ACK + TCP_RST; - else if (tcp_push) - action = action | TCP_PUSH; - break; - case TCP_CLOSE_WAIT: - debug_cond(DEBUG_INT_STATE, "TCP_CLOSE_WAIT (%x)\n", tcp_flags); - action = TCP_DATA; - break; - case TCP_FIN_WAIT_2: - debug_cond(DEBUG_INT_STATE, "TCP_FIN_WAIT_2 (%x)\n", tcp_flags); - if (tcp_ack) { - action = TCP_PUSH | TCP_ACK; - tcp->state = TCP_CLOSED; - puts("\n"); - } else if (tcp_syn) { - action = TCP_DATA; - } else if (tcp_fin) { - action = TCP_DATA; + if (tcp_flags & TCP_SYN) { + tcp_send_packet(tcp, TCP_RST, tcp_ack_num, 0, 0); + tcp_stream_set_status(tcp, TCP_ERR_RST); + tcp_stream_set_state(tcp, TCP_CLOSED); + return; } - break; - case TCP_FIN_WAIT_1: - debug_cond(DEBUG_INT_STATE, "TCP_FIN_WAIT_1 (%x)\n", tcp_flags); - if (tcp_fin) { - tcp->rcv_nxt++; - action = TCP_ACK | TCP_FIN; - tcp->state = TCP_FIN_WAIT_2; + + if (!(tcp_flags & TCP_ACK)) + return; + + if (tcp_rx_check_ack_num(tcp, tcp_seq_num, tcp_ack_num, + tcp_win_size) == TCP_PACKET_DROP) { + return; } - if (tcp_syn) - action = TCP_RST; - if (tcp_ack) - tcp->state = TCP_CLOSED; - break; - case TCP_CLOSING: - debug_cond(DEBUG_INT_STATE, "TCP_CLOSING (%x)\n", tcp_flags); - if (tcp_ack) { - action = TCP_PUSH; - tcp->state = TCP_CLOSED; - puts("\n"); - } else if (tcp_syn) { - action = TCP_RST; - } else if (tcp_fin) { - action = TCP_DATA; + + if (tcp_rx_user_data(tcp, tcp_seq_num, + ((char *)b) + pkt_len - payload_len, + payload_len) == TCP_PACKET_DROP) { + return; + } + + if (tcp_flags & TCP_FIN) { + tcp->fin_rx = 1; + tcp->fin_rx_seq = tcp_seq_num + payload_len + 1; + tcp_hole(tcp, tcp_seq_num + payload_len, 1); + action = tcp_stream_fin_needed(tcp, tcp->snd_una) | TCP_ACK; + tcp_send_packet(tcp, action, tcp->snd_una, tcp->rcv_nxt, 0); + } + + if (tcp->fin_rx && (tcp->fin_rx_seq == tcp->rcv_nxt)) { + /* all rx data were processed */ + switch (tcp->state) { + case TCP_ESTABLISHED: + tcp_stream_set_state(tcp, TCP_LAST_ACK); + tcp_send_packet_with_retry(tcp, TCP_ACK | TCP_FIN, + tcp->snd_nxt, 0, 0); + tcp->snd_nxt++; + break; + + case TCP_FIN_WAIT_1: + if (tcp_ack_num == tcp->snd_nxt) + tcp_stream_set_state(tcp, TCP_CLOSED); + else + tcp_stream_set_state(tcp, TCP_CLOSING); + break; + + case TCP_FIN_WAIT_2: + tcp_stream_set_state(tcp, TCP_CLOSED); + break; + + default: + break; + } + } + + if ((tcp->state == TCP_FIN_WAIT_1) && + tcp_stream_fin_needed(tcp, tcp->snd_una)) { + /* all tx data were acknowledged */ + tcp_send_packet_with_retry(tcp, TCP_ACK | TCP_FIN, + tcp->snd_una, 0, 0); } - break; } - return action; } /** @@ -667,9 +1114,6 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len) { int tcp_len = pkt_len - IP_HDR_SIZE; u16 tcp_rx_xsum = b->ip.hdr.ip_sum; - u8 tcp_action = TCP_DATA; - u32 tcp_seq_num, tcp_ack_num; - int tcp_hdr_len, payload_len; struct tcp_stream *tcp; struct in_addr src; @@ -713,54 +1157,57 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len) if (!tcp) return; - tcp_hdr_len = GET_TCP_HDR_LEN_IN_BYTES(b->ip.hdr.tcp_hlen); - payload_len = tcp_len - tcp_hdr_len; + tcp_rx_state_machine(tcp, b, pkt_len); + tcp_stream_put(tcp); +} - if (tcp_hdr_len > TCP_HDR_SIZE) - tcp_parse_options(tcp, (uchar *)b + IP_TCP_HDR_SIZE, - tcp_hdr_len - TCP_HDR_SIZE); - /* - * Incoming sequence and ack numbers are server's view of the numbers. - * The app must swap the numbers when responding. - */ - tcp_seq_num = ntohl(b->ip.hdr.tcp_seq); - tcp_ack_num = ntohl(b->ip.hdr.tcp_ack); +struct tcp_stream *tcp_stream_connect(struct in_addr rhost, u16 rport) +{ + struct tcp_stream *tcp; - /* Packets are not ordered. Send to app as received. */ - tcp_action = tcp_state_machine(tcp, b->ip.hdr.tcp_flags, - tcp_seq_num, payload_len); + tcp = tcp_stream_add(rhost, rport, random_port()); + if (tcp == NULL) + return NULL; - tcp_activity_count++; - if (tcp_activity_count > TCP_ACTIVITY) { - puts("| "); - tcp_activity_count = 0; - } + tcp->iss = tcp_get_start_seq(); + tcp->snd_una = tcp->iss; + tcp->snd_nxt = tcp->iss + 1; - if ((tcp_action & TCP_PUSH) || payload_len > 0) { - debug_cond(DEBUG_DEV_PKT, - "TCP Notify (action=%x, Seq=%u,Ack=%u,Pay%d)\n", - tcp_action, tcp_seq_num, tcp_ack_num, payload_len); + tcp_stream_set_state(tcp, TCP_SYN_SENT); + tcp_send_packet_with_retry(tcp, TCP_SYN, tcp->snd_una, 0, 0); + return tcp; +} - (*tcp_packet_handler) (tcp, (uchar *)b + pkt_len - payload_len, - tcp_seq_num, tcp_ack_num, tcp_action, - payload_len); +void tcp_stream_reset(struct tcp_stream *tcp) +{ + if (tcp->state == TCP_CLOSED) + return; - } else if (tcp_action != TCP_DATA) { - debug_cond(DEBUG_DEV_PKT, - "TCP Action (action=%x,Seq=%u,Ack=%u,Pay=%d)\n", - tcp_action, tcp_ack_num, tcp->rcv_nxt, payload_len); - - /* - * Warning: Incoming Ack & Seq sequence numbers are transposed - * here to outgoing Seq & Ack sequence numbers - */ - net_send_tcp_packet(0, tcp->rhost, tcp->rport, tcp->lport, - (tcp_action & (~TCP_PUSH)), - tcp_ack_num, tcp->rcv_nxt); - } + tcp_stream_set_time_handler(tcp, 0, NULL); + tcp_send_packet(tcp, TCP_RST, tcp->snd_una, 0, 0); + tcp_stream_set_status(tcp, TCP_ERR_RST); + tcp_stream_set_state(tcp, TCP_CLOSED); } -struct tcp_stream *tcp_stream_connect(struct in_addr rhost, u16 rport) +void tcp_stream_close(struct tcp_stream *tcp) { - return tcp_stream_add(rhost, rport, random_port()); + switch (tcp->state) { + case TCP_SYN_SENT: + tcp_stream_reset(tcp); + break; + case TCP_SYN_RECEIVED: + case TCP_ESTABLISHED: + tcp->fin_tx = 1; + tcp->fin_tx_seq = tcp->snd_nxt; + if (tcp_stream_fin_needed(tcp, tcp->snd_una)) { + /* all tx data were acknowledged */ + tcp_send_packet_with_retry(tcp, TCP_ACK | TCP_FIN, + tcp->snd_una, 0, 0); + } + tcp_stream_set_state(tcp, TCP_FIN_WAIT_1); + tcp->snd_nxt++; + break; + default: + break; + } } diff --git a/net/wget.c b/net/wget.c index ad5db21e97e..ba95efa61c1 100644 --- a/net/wget.c +++ b/net/wget.c @@ -21,48 +21,26 @@ DECLARE_GLOBAL_DATA_PTR; /* The default, change with environment variable 'httpdstp' */ #define SERVER_PORT 80 +#define HASHES_PER_LINE 65 + +#define HTTP_MAX_HDR_LEN 2048 + static const char bootfile1[] = "GET "; static const char bootfile3[] = " HTTP/1.0\r\n\r\n"; static const char http_eom[] = "\r\n\r\n"; -static const char http_ok[] = "200"; -static const char content_len[] = "Content-Length"; +static const char http_ok[] = " 200 "; +static const char content_len[] = "Content-Length:"; static const char linefeed[] = "\r\n"; -static int wget_timeout_count; -struct tcp_stream *tcp; - -struct pkt_qd { - uchar *pkt; - unsigned int tcp_seq_num; - unsigned int len; -}; - -/* - * This is a control structure for out of order packets received. - * The actual packet bufers are in the kernel space, and are - * expected to be overwritten by the downloaded image. - */ -#define PKTQ_SZ (PKTBUFSRX / 4) -static struct pkt_qd pkt_q[PKTQ_SZ]; -static int pkt_q_idx; +static struct in_addr web_server_ip; +static unsigned int server_port; static unsigned long content_length; static unsigned int packets; - -static unsigned int initial_data_seq_num; -static unsigned int next_data_seq_num; - -static enum wget_state current_wget_state; +static u32 http_hdr_size; +static int wget_tsize_num_hash; static char *image_url; -static unsigned int wget_timeout = WGET_TIMEOUT; - static enum net_loop_state wget_loop_state; -/* Timeout retry parameters */ -static u8 retry_action; /* actions for TCP retry */ -static unsigned int retry_tcp_ack_num; /* TCP retry acknowledge number*/ -static unsigned int retry_tcp_seq_num; /* TCP retry sequence number */ -static int retry_len; /* TCP retry length */ - static ulong wget_load_size; /** @@ -95,7 +73,6 @@ static int wget_init_load_size(void) static inline int store_block(uchar *src, unsigned int offset, unsigned int len) { ulong store_addr = image_load_addr + offset; - ulong newsize = offset + len; uchar *ptr; if (IS_ENABLED(CONFIG_LMB)) { @@ -115,330 +92,150 @@ static inline int store_block(uchar *src, unsigned int offset, unsigned int len) ptr = map_sysmem(store_addr, len); memcpy(ptr, src, len); unmap_sysmem(ptr); - - if (net_boot_file_size < (offset + len)) - net_boot_file_size = newsize; - return 0; } -/** - * wget_send_stored() - wget response dispatcher - * - * WARNING, This, and only this, is the place in wget.c where - * SEQUENCE NUMBERS are swapped between incoming (RX) - * and outgoing (TX). - * Procedure wget_handler() is correct for RX traffic. - */ -static void wget_send_stored(void) +static void show_block_marker(void) { - u8 action = retry_action; - int len = retry_len; - unsigned int tcp_ack_num = retry_tcp_seq_num + (len == 0 ? 1 : len); - unsigned int tcp_seq_num = retry_tcp_ack_num; - uchar *ptr, *offset; - - switch (current_wget_state) { - case WGET_CLOSED: - debug_cond(DEBUG_WGET, "wget: send SYN\n"); - current_wget_state = WGET_CONNECTING; - net_send_tcp_packet(0, tcp->rhost, tcp->rport, tcp->lport, action, - tcp_seq_num, tcp_ack_num); - packets = 0; - break; - case WGET_CONNECTING: - pkt_q_idx = 0; - net_send_tcp_packet(0, tcp->rhost, tcp->rport, tcp->lport, action, - tcp_seq_num, tcp_ack_num); - - ptr = net_tx_packet + net_eth_hdr_size() + - IP_TCP_HDR_SIZE + TCP_TSOPT_SIZE + 2; - offset = ptr; - - memcpy(offset, &bootfile1, strlen(bootfile1)); - offset += strlen(bootfile1); - - memcpy(offset, image_url, strlen(image_url)); - offset += strlen(image_url); - - memcpy(offset, &bootfile3, strlen(bootfile3)); - offset += strlen(bootfile3); - net_send_tcp_packet((offset - ptr), tcp->rhost, tcp->rport, tcp->lport, - TCP_PUSH, tcp_seq_num, tcp_ack_num); - current_wget_state = WGET_CONNECTED; - break; - case WGET_CONNECTED: - case WGET_TRANSFERRING: - case WGET_TRANSFERRED: - net_send_tcp_packet(0, tcp->rhost, tcp->rport, tcp->lport, action, - tcp_seq_num, tcp_ack_num); - break; - } -} + int cnt; -static void wget_send(u8 action, unsigned int tcp_seq_num, - unsigned int tcp_ack_num, int len) -{ - retry_action = action; - retry_tcp_ack_num = tcp_ack_num; - retry_tcp_seq_num = tcp_seq_num; - retry_len = len; + if (content_length != -1) { + if (net_boot_file_size > content_length) + content_length = net_boot_file_size; - wget_send_stored(); + cnt = net_boot_file_size * 50 / content_length; + while (wget_tsize_num_hash < cnt) { + putc('#'); + wget_tsize_num_hash++; + } + } else { + if ((packets % 10) == 0) + putc('#'); + else if (((packets + 1) % (10 * HASHES_PER_LINE)) == 0) + puts("\n"); + } } -void wget_fail(char *error_message, unsigned int tcp_seq_num, - unsigned int tcp_ack_num, u8 action) +static void tcp_stream_on_closed(struct tcp_stream *tcp) { - printf("wget: Transfer Fail - %s\n", error_message); - net_set_timeout_handler(0, NULL); - wget_send(action, tcp_seq_num, tcp_ack_num, 0); + if (tcp->status != TCP_ERR_OK) + wget_loop_state = NETLOOP_FAIL; + + if (wget_loop_state != NETLOOP_SUCCESS) + printf("\nwget: Transfer Fail, TCP status - %d\n", tcp->status); + else + printf("\nPackets received %d, Transfer Successful\n", packets); + net_set_state(wget_loop_state); } -void wget_success(u8 action, unsigned int tcp_seq_num, - unsigned int tcp_ack_num, int len, int packets) +static void tcp_stream_on_rcv_nxt_update(struct tcp_stream *tcp, u32 rx_bytes) { - printf("Packets received %d, Transfer Successful\n", packets); - wget_send(action, tcp_seq_num, tcp_ack_num, len); -} + char *pos, *tail; + uchar saved, *ptr; + int i; -/* - * Interfaces of U-BOOT - */ -static void wget_timeout_handler(void) -{ - if (++wget_timeout_count > WGET_RETRY_COUNT) { - puts("\nRetry count exceeded; starting again\n"); - wget_send(TCP_RST, 0, 0, 0); - net_start_again(); - } else { - puts("T "); - net_set_timeout_handler(wget_timeout + - WGET_TIMEOUT * wget_timeout_count, - wget_timeout_handler); - wget_send_stored(); + if (http_hdr_size != 0) { + net_boot_file_size = rx_bytes - http_hdr_size; + show_block_marker(); + return; } -} -#define PKT_QUEUE_OFFSET 0x20000 -#define PKT_QUEUE_PACKET_SIZE 0x800 + ptr = map_sysmem(image_load_addr, rx_bytes + 1); -static void wget_connected(uchar *pkt, unsigned int tcp_seq_num, - u8 action, unsigned int tcp_ack_num, unsigned int len) -{ - uchar *pkt_in_q; - char *pos; - int hlen, i; - uchar *ptr1; + saved = ptr[rx_bytes]; + ptr[rx_bytes] = '\0'; + pos = strstr((char *)ptr, http_eom); + ptr[rx_bytes] = saved; - pkt[len] = '\0'; - pos = strstr((char *)pkt, http_eom); + if (pos == NULL) { + if ((rx_bytes < HTTP_MAX_HDR_LEN) && + (tcp->state == TCP_ESTABLISHED)) + goto end; - if (!pos) { - debug_cond(DEBUG_WGET, - "wget: Connected, data before Header %p\n", pkt); - pkt_in_q = (void *)image_load_addr + PKT_QUEUE_OFFSET + - (pkt_q_idx * PKT_QUEUE_PACKET_SIZE); - - ptr1 = map_sysmem((phys_addr_t)pkt_in_q, len); - memcpy(ptr1, pkt, len); - unmap_sysmem(ptr1); - - pkt_q[pkt_q_idx].pkt = pkt_in_q; - pkt_q[pkt_q_idx].tcp_seq_num = tcp_seq_num; - pkt_q[pkt_q_idx].len = len; - pkt_q_idx++; - - if (pkt_q_idx >= PKTQ_SZ) { - printf("wget: Fatal error, queue overrun!\n"); - net_set_state(NETLOOP_FAIL); + printf("ERROR: misssed HTTP header\n"); + tcp_stream_close(tcp); + wget_loop_state = NETLOOP_FAIL; + goto end; + } - return; - } - } else { - debug_cond(DEBUG_WGET, "wget: Connected HTTP Header %p\n", pkt); - /* sizeof(http_eom) - 1 is the string length of (http_eom) */ - hlen = pos - (char *)pkt + sizeof(http_eom) - 1; - pos = strstr((char *)pkt, linefeed); - if (pos > 0) - i = pos - (char *)pkt; - else - i = hlen; - printf("%.*s", i, pkt); - - current_wget_state = WGET_TRANSFERRING; - - initial_data_seq_num = tcp_seq_num + hlen; - next_data_seq_num = tcp_seq_num + len; - - if (strstr((char *)pkt, http_ok) == 0) { - debug_cond(DEBUG_WGET, - "wget: Connected Bad Xfer\n"); - wget_loop_state = NETLOOP_FAIL; - wget_send(action, tcp_seq_num, tcp_ack_num, len); - } else { - debug_cond(DEBUG_WGET, - "wget: Connctd pkt %p hlen %x\n", - pkt, hlen); - - pos = strstr((char *)pkt, content_len); - if (!pos) { - content_length = -1; - } else { - pos += sizeof(content_len) + 2; - strict_strtoul(pos, 10, &content_length); - debug_cond(DEBUG_WGET, - "wget: Connected Len %lu\n", - content_length); - } - - net_boot_file_size = 0; - - if (len > hlen) { - if (store_block(pkt + hlen, 0, len - hlen) != 0) { - wget_loop_state = NETLOOP_FAIL; - wget_fail("wget: store error\n", tcp_seq_num, tcp_ack_num, action); - net_set_state(NETLOOP_FAIL); - return; - } - } + http_hdr_size = pos - (char *)ptr + strlen(http_eom); + *pos = '\0'; + + pos = strstr((char *)ptr, linefeed); + if (pos > 0) + i = pos - (char *)ptr; + else + i = http_hdr_size - strlen(http_eom); + printf("%.*s\n", i, ptr); + + if (strstr((char *)ptr, http_ok) == NULL) { + debug_cond(DEBUG_WGET, "wget: Connected Bad Xfer\n"); + tcp_stream_close(tcp); + wget_loop_state = NETLOOP_FAIL; + goto end; + } - debug_cond(DEBUG_WGET, - "wget: Connected Pkt %p hlen %x\n", - pkt, hlen); - - for (i = 0; i < pkt_q_idx; i++) { - int err; - - ptr1 = map_sysmem( - (phys_addr_t)(pkt_q[i].pkt), - pkt_q[i].len); - err = store_block(ptr1, - pkt_q[i].tcp_seq_num - - initial_data_seq_num, - pkt_q[i].len); - unmap_sysmem(ptr1); - debug_cond(DEBUG_WGET, - "wget: Connctd pkt Q %p len %x\n", - pkt_q[i].pkt, pkt_q[i].len); - if (err) { - wget_loop_state = NETLOOP_FAIL; - wget_fail("wget: store error\n", tcp_seq_num, tcp_ack_num, action); - net_set_state(NETLOOP_FAIL); - return; - } - } - } + debug_cond(DEBUG_WGET, "wget: Connctd pkt %p hlen %x\n", + ptr, http_hdr_size); + + pos = strstr((char *)ptr, content_len); + if (!pos) { + content_length = -1; + } else { + pos += strlen(content_len) + 1; + content_length = simple_strtoul(pos, &tail, 10); + if ((*tail != '\r') && (*tail != '\n') && (*tail != '\0')) + content_length = -1; + printf("%s %d\n", content_len, (int)content_length); } - wget_send(action, tcp_seq_num, tcp_ack_num, len); + + net_boot_file_size = rx_bytes - http_hdr_size; + memmove(ptr, ptr + http_hdr_size, net_boot_file_size); + +end: + unmap_sysmem(ptr); + + wget_loop_state = NETLOOP_SUCCESS; } -/** - * wget_handler() - TCP handler of wget - * @tcp: TCP stream - * @pkt: pointer to the application packet - * @tcp_seq_num: TCP sequential number - * @tcp_ack_num: TCP acknowledgment number - * @action: TCP action (SYN, ACK, FIN, etc) - * @len: packet length - * - * In the "application push" invocation, the TCP header with all - * its information is pointed to by the packet pointer. - */ -static void wget_handler(struct tcp_stream *tcp, uchar *pkt, - u32 tcp_seq_num, u32 tcp_ack_num, - u8 action, unsigned int len) +static u32 tcp_stream_rx(struct tcp_stream *tcp, u32 rx_offs, void *buf, u32 len) { - enum tcp_state wget_tcp_state = tcp_stream_get_state(tcp); - - net_set_timeout_handler(wget_timeout, wget_timeout_handler); packets++; + store_block(buf, rx_offs - http_hdr_size, len); + return len; +} - switch (current_wget_state) { - case WGET_CLOSED: - debug_cond(DEBUG_WGET, "wget: Handler: Error!, State wrong\n"); - break; - case WGET_CONNECTING: - debug_cond(DEBUG_WGET, - "wget: Connecting In len=%x, Seq=%u, Ack=%u\n", - len, tcp_seq_num, tcp_ack_num); - if (!len) { - if (wget_tcp_state == TCP_ESTABLISHED) { - debug_cond(DEBUG_WGET, - "wget: Cting, send, len=%x\n", len); - wget_send(action, tcp_seq_num, tcp_ack_num, - len); - } else { - printf("%.*s", len, pkt); - wget_fail("wget: Handler Connected Fail\n", - tcp_seq_num, tcp_ack_num, action); - } - } - break; - case WGET_CONNECTED: - debug_cond(DEBUG_WGET, "wget: Connected seq=%u, len=%x\n", - tcp_seq_num, len); - if (!len) { - wget_fail("Image not found, no data returned\n", - tcp_seq_num, tcp_ack_num, action); - } else { - wget_connected(pkt, tcp_seq_num, action, tcp_ack_num, len); - } - break; - case WGET_TRANSFERRING: - debug_cond(DEBUG_WGET, - "wget: Transferring, seq=%x, ack=%x,len=%x\n", - tcp_seq_num, tcp_ack_num, len); - - if (next_data_seq_num != tcp_seq_num) { - debug_cond(DEBUG_WGET, "wget: seq=%x packet was lost\n", next_data_seq_num); - return; - } - next_data_seq_num = tcp_seq_num + len; +static u32 tcp_stream_tx(struct tcp_stream *tcp, u32 tx_offs, void *buf, u32 maxlen) +{ + int ret; - if (store_block(pkt, tcp_seq_num - initial_data_seq_num, len) != 0) { - wget_fail("wget: store error\n", - tcp_seq_num, tcp_ack_num, action); - net_set_state(NETLOOP_FAIL); - return; - } + if (tx_offs != 0) + return 0; - switch (wget_tcp_state) { - case TCP_FIN_WAIT_2: - wget_send(TCP_ACK, tcp_seq_num, tcp_ack_num, len); - fallthrough; - case TCP_SYN_SENT: - case TCP_SYN_RECEIVED: - case TCP_CLOSING: - case TCP_FIN_WAIT_1: - case TCP_CLOSED: - net_set_state(NETLOOP_FAIL); - break; - case TCP_ESTABLISHED: - wget_send(TCP_ACK, tcp_seq_num, tcp_ack_num, - len); - wget_loop_state = NETLOOP_SUCCESS; - break; - case TCP_CLOSE_WAIT: /* End of transfer */ - current_wget_state = WGET_TRANSFERRED; - wget_send(action | TCP_ACK | TCP_FIN, - tcp_seq_num, tcp_ack_num, len); - break; - } - break; - case WGET_TRANSFERRED: - printf("Packets received %d, Transfer Successful\n", packets); - net_set_state(wget_loop_state); - break; - } + ret = snprintf(buf, maxlen, "%s%s%s", bootfile1, image_url, bootfile3); + return ret; +} + +static int tcp_stream_on_create(struct tcp_stream *tcp) +{ + if ((tcp->rhost.s_addr != web_server_ip.s_addr) || + (tcp->rport != server_port)) + return 0; + + tcp->max_retry_count = WGET_RETRY_COUNT; + tcp->initial_timeout = WGET_TIMEOUT; + tcp->on_closed = tcp_stream_on_closed; + tcp->on_rcv_nxt_update = tcp_stream_on_rcv_nxt_update; + tcp->rx = tcp_stream_rx; + tcp->tx = tcp_stream_tx; + return 1; } #define BLOCKSIZE 512 void wget_start(void) { - struct in_addr web_server_ip; - unsigned int server_port; + struct tcp_stream *tcp; image_url = strchr(net_boot_file_name, ':'); if (image_url > 0) { @@ -486,12 +283,6 @@ void wget_start(void) } } - net_set_timeout_handler(wget_timeout, wget_timeout_handler); - tcp_set_tcp_handler(wget_handler); - - wget_timeout_count = 0; - current_wget_state = WGET_CLOSED; - /* * Zero out server ether to force arp resolution in case * the server ip for the previous u-boot command, for example dns @@ -500,14 +291,21 @@ void wget_start(void) memset(net_server_ethaddr, 0, 6); + packets = 0; + net_boot_file_size = 0; + http_hdr_size = 0; + wget_tsize_num_hash = 0; + wget_loop_state = NETLOOP_FAIL; + server_port = env_get_ulong("httpdstp", 10, SERVER_PORT) & 0xffff; + tcp_stream_set_on_create_handler(tcp_stream_on_create); tcp = tcp_stream_connect(web_server_ip, server_port); if (tcp == NULL) { + printf("No free tcp streams\n"); net_set_state(NETLOOP_FAIL); return; } - - wget_send(TCP_SYN, 0, 0, 0); + tcp_stream_put(tcp); } #if (IS_ENABLED(CONFIG_CMD_DNS)) From patchwork Sat Aug 24 09:27:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Kshevetskiy X-Patchwork-Id: 1976363 X-Patchwork-Delegate: pbrobinson@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.a=rsa-sha256 header.s=selector2 header.b=nY8u0++n; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WrWpH3J16z1yXd for ; Sat, 24 Aug 2024 19:28:39 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 08F9388B69; Sat, 24 Aug 2024 11:27:40 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.b="nY8u0++n"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 152B788CE5; Sat, 24 Aug 2024 11:27:38 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,SPF_HELO_PASS, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 Received: from EUR05-AM6-obe.outbound.protection.outlook.com (mail-am6eur05on20720.outbound.protection.outlook.com [IPv6:2a01:111:f403:2612::720]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 1E45B8890D for ; Sat, 24 Aug 2024 11:27:36 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mikhail.kshevetskiy@genexis.eu ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=DvqiFsbuzzTGHZuNIOcxYw8OZWZlGldkZvqkqIlDEpGrGKxTSzQPtZOE8a3KT/JYVtqbuSefluTFlVDamX/mxfX3so2xJs+JsAbRGnfJ2zhwIWok7vDauFXmVDT3YD+asoeUZssW94szb0a9Rh4T8WAAvC+tefG9APo8pwcYTjqX5U8hicPTF3gQvoAJtEmA4HyhmEO3SWHJk6i5JMHsdLYk0IPZ6LrW8bLLB4v61FpbaNRp97ZRdv2oM9VZpJ1y2Jo3g2FuBhwTGqEIKuXEfvWd0opfgnDaRkq70oU2cO2jt+mhe8SC/zX6lMIMrCKGowMSIvr90cEagzfh/YNMuA== 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=3/QeAf0KtFRXHltMI5OcYo6yFh+r99RkW9Ga5GJHjiY=; b=vWpf3iPEyyR/ckdeGU4g60okrWTOM5o3h9tcYdm0kOtcqBp7ZKMAe/Vevak/04cm7S1EGp3kIqFcJV3YWE1Y0BWugpUj03p7ZPNMVUqw5keyhAT1cga0NDhlJH3HflqvEyGLcRSn4F0X2WCPyPcrwrEVdEGP44J8GVdqqe/Q9liRdFQ+41sxxWF1SsfLP8uXEroiD7sq8pDZbNdvLu4Q5YntjIhISL5nUDRC+5hCPfaVR/MlzGWSgHUYxmx1Qvt/92Uh4wuQ622ZnIqMA2z40MCtWCDzfQ+CoeqR57fHPrBum/S78uni/SMX2xMmnknkdj8Azova8XHQ1MXmT2khdg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=genexis.eu; dmarc=pass action=none header.from=iopsys.eu; dkim=pass header.d=iopsys.eu; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iopsys.eu; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=3/QeAf0KtFRXHltMI5OcYo6yFh+r99RkW9Ga5GJHjiY=; b=nY8u0++nhhph95gHCLfn1KYqz12b6F+ADMqI1U8M9jlyaDbkvko/009t7b1Gnw8d7wAdMj6iAu8egdMq+Gd5cI9o+mNuQqz9okg/gdpDQeIH7QUDETYS/gtb9RUx9q8eTf3DfwPcQt76y/4Gos9LdUp2HMZBpiHr1COyjy7WQw4lbNbEugFNeG6vsnBHTgOxogBRJkv/u4nWvjFYjoQZT7w5oDEcBroWiO4sxKMZ9wqlZoxHtKn9Nqf5YXi2EHPJ/VjyMnccz3j0Okv8snvu1OJ5dfu1V+/f2R6RfX4e5nMHBvqPok/wPm+DbMlTyZtOSdd22KTX5ZXLt6vj2lh85g== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=iopsys.eu; Received: from GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) by AS4PR08MB7601.eurprd08.prod.outlook.com (2603:10a6:20b:4ff::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7897.18; Sat, 24 Aug 2024 09:27:34 +0000 Received: from GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0]) by GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0%2]) with mapi id 15.20.7918.011; Sat, 24 Aug 2024 09:27:34 +0000 From: Mikhail Kshevetskiy To: Tom Rini , Joe Hershberger , Ramon Fried , Mattijs Korpershoek , Simon Glass , Heinrich Schuchardt , AKASHI Takahiro , Michal Simek , Francis Laniel , Anand Moon , Mikhail Kshevetskiy , Marek Vasut , Ilias Apalodimas , Masahisa Kojima , Sean Anderson , Baruch Siach , Yasuharu Shibata , u-boot@lists.denx.de Subject: [PATCH v5 07/11] net/tcp: simplify tcp header filling code Date: Sat, 24 Aug 2024 12:27:12 +0300 Message-ID: <20240824092716.1042696-8-mikhail.kshevetskiy@iopsys.eu> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240824092716.1042696-1-mikhail.kshevetskiy@iopsys.eu> References: <20240824092716.1042696-1-mikhail.kshevetskiy@iopsys.eu> X-ClientProxiedBy: GV3P280CA0011.SWEP280.PROD.OUTLOOK.COM (2603:10a6:150:b::7) To GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: GV2PR08MB8121:EE_|AS4PR08MB7601:EE_ X-MS-Office365-Filtering-Correlation-Id: 8baddce0-d50e-4d47-975c-08dcc41efcae X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|366016|376014|1800799024|52116014|7416014|921020|38350700014; X-Microsoft-Antispam-Message-Info: FASmzdr0Lk0/iC9hmGjeytBKilqLIt0inZuVX/mWFjxKksCf0guBmrGi+GRWPMtLdsjbEetxYDAhJ77Z/f2r6EqZfw1XBD6Kr8AiNVDB33txR9Ma9pGxLKM/LRJyvrZn1d8lEMypgDjC52YOD2j+UNZ3eUX/643aBxBDTA9rbcK2PZdBpr+c2FoxLPcPJ42JUwYsuzTLF0TmXoZkoVQFdmFJufjNt0VMD2iob1NapMOnubvhMDU20atNLNiJauOUWPx0+T8w1ZXgR6ZO1JqJbpVQK0pKLJ+QqaBW6W5bE73Y9RhKQ5ejW4YRI31WCawRHFbTTzkTQLVfSL9jarrPNgVs9FYVStHE7XvP8Fn7YkKnMr48VWZctswstjG22vnY67Jjy5m5lCcbRIj9FKkvDpviNjCfJaSVqAPTJuLbkZnFmN3lgGZD25sxCbjREvfkQbvqvh/NQsd98imcBObUWhvOyX+cMXyJ/qqJdvKfjpTpQJQkAdXW7TtwSLryyEOrebxBSk3i/1DpPd8rNU8vMK4NNpIC91OaCeJYDmLGk/Q1FJbl6iPmjNFTo2h2H3dzmbP3lhPOMsB6Gh5zCzRxj9OL95N5AoerKCbFHm1wrPOP4GbopgCNXarIpUdticKN8bX2ZK8fBLs3UAwKqKrsUTG8RwmSqlCr5Bv7yiKUg7uH1oqlrbGwd/oBdkXcEy5ER0mOpCLhpSYQwx5axHHYK01N2wg//XUTT+uKDllY/RYwYlfvykAHbRecbpWeyOxlEBCpvP2y22e48KUWhAQL3q7RVyG0bWq55S/vk5yT4/i3JZKzzTmPPmC/TJ9FqgtyNsbJECC6zC2//5jFzS9QDa1tkr6ko33rjhlsG06qd14zxG7gezFLUjjvLfOQ34wG08QbR6xyI1Wrer+N0t8wEsTjN67P7laTICkIDimEbfRP5pIeLHdjWhlt82h7ks2lwiAUslyG1MAbsRB7ehqaAgR7rvdkuHGEeICGRK1vKm0YwA4lLEjvCq9oRK7Hhef5I61O9oDQDLD5HiPKXB0wyLCzGpf66KurrqWfYJ5BAi/lU1+lP1ID7dFP1NfY1o4d/c84EWv/E2u05ozDkfLi+7gDK+z/0vqTuj1Go0P5HEPtNEiA+sgIrQd47oKbFy4y4LX1KccSbENihWdO+ciXA0jzjgSs1Eqq1SHbGhnPpvzJE2/m6pPR2ktC9C4C00XwrwNetOW7S8PpcqcPgGOGNLGmtJsFmBqL7eQa62GyPvk1lYwb3w3feTJ73fSY+wLL12iv6fe7v7o1dceO3Ya5sUnfYuhqZeZjygQ1YzIM613La68XPjd+Jbhwk1LgSl2aR9hBD1up6YpO36CkowFca9PPT/QWlClkTxvD/reg85koFTRiYho7vLgUg5deKYnQTvAkI5mPPexT4FaJyjShPok+7vG6kDUbmB0FEWBOeBM= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:GV2PR08MB8121.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(366016)(376014)(1800799024)(52116014)(7416014)(921020)(38350700014); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: bQcEBtFR3hZRCBzkvGgfB35WMzqb7QEBL3V63SwdK1vhDPZnCZRNqBMOg2caOdz8XxzVjnYKbyXJEzfqZihdQL3BlSygfGVOkhOmoh4PVo9RsiqdhmKd9GnonGa7oQGr25fhN3nu/u6RIQGMM/t4F0qFS7qUB4ZEKYpdXqCednMXmJ0Tq6PuYrMEAlCOZFBF5ZPxMdIgvlkyUN7sPUtqXnQq5T+/hgrzuzY28UuPDpU5Ifo7gu13GyXsIJcevmc/NdhlYYs1W8vpiTwCmHjOogjaC3lw23cHHGgNvrr6AaolVa2w6/6VV7LRvJvAuHQO1z2xMYDYud72kG6VdRvakfCa9kbjwUfAAp9M0vORRMNOGxPIgfHrbEQgkCGEuwvL8jgQrpLqCO390x2GtF16vnZ7kWVcM6rzmguuQCBqNN92E2Yeqx3lyBWQZw0vOswahfoMdevBH7hxYBmj4NDuXykWWx433BBFbgkMu8xbTJqPeoaZ4WL5OZXd7t4CX7YanjRy+yMbLxhG84o++Hs5hih6JGMknlFu33EvriqLaLCaD+evATgcnShZsK58OPHXGCgOsJcLACOqiP9okupIpq144toH19MVwvcLy6JSR/Od7UwFYfPnMQ8wR54dlZ84AFRLdU18e0Hh2ea2fUiCctQ5B/PhyoGZ23IID+dWhnryKxeTQfIAb/QbAIT+AkNa52BblMcLIbRarGIt/3ynACKiiu4kStBT/VWNv1VeZrg5hx7hI5GP3jmYILt+W/v+8eyqEYV7f7nNNd/PGYdvHeR5TUe84Zcstn8XJni/cIf1JXp3dA6FaHCzEXF1l2BdTF6DDRdnYqqDmTIqWZyldDpotjnjMYqiICwclPLI4FE3yASgGJmkO857YTDNKMlmdacTbpomujZRX0OMLiJ7DnbfIQtzwu6we0tXdvoK3kycYrn0hSh6mobPQ1XRfSkVUYJaRKq9ddTOoCDwM6Su1pz7xYIjfTx8VPqR4WdHAu/bSaZQPojhskCp9c0uvJvdtwj/P6XGU43GwklQmUocsktCPOT5J9UVCzwQh6gIfoMZTxcVI8e/kV5oWbKXhkPPAuhXwjxBtKNPzf+6oMQXvhtLYjaBJFeH6omAqvLgZbXXurITRTXkFnsXifWHAQB0OTx0b1WrDTUsLeyhq6AUB7hMT5is8O+kBbJB393gbq7ErnpGa3RLTMe9w2hJMLgU1Xoct467KqQv90ghzQGeIVVbPmwGVTKpDGJIS3Dm7cGd1iEvJmhOr7yWhK5pg03U1SzCziOWzNLhMVpUJeA801du+dETgZEnHPpmm/wJj17rqdVVd1Um7b8rAJLpjn8ENUB+0xJh33gtSeEHc5HlymdKmWjGYyhNLbeqG6b4a8Q7PoKqrcwZhE680Mk0aPXnij16XOBz1CW4JrU0qIB84J/4jfT0TW1zXP6f35sHpuLNE8z9iDvGqR8k4+7kWyr2LEWyUCZrwJytaAOoav46a1MbDTycuj7jK9REBjMhKs+TmT4MA4HXfvubxRq+AV4sRRlkPU63tCcHinHD5FVE4S7mUP0D0FglmqONlJV2+J2M7iwibUh3dKXfvqwvIjxRKgctLBq2bpkkAFxeJDf6/DJdpHpc53yjR9Y3nC8KGUo= X-OriginatorOrg: iopsys.eu X-MS-Exchange-CrossTenant-Network-Message-Id: 8baddce0-d50e-4d47-975c-08dcc41efcae X-MS-Exchange-CrossTenant-AuthSource: GV2PR08MB8121.eurprd08.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Aug 2024 09:27:34.8482 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 8d891be1-7bce-4216-9a99-bee9de02ba58 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: WGv9NsF0JkandX/2xe4A/p7GwrpbcpHqCjX81vag3OgZV23ITiRDLN4E0wwPJneVdvpqaFECmYUEs5ptNWVzvh2SLjmUN9rG7ajLuBhf4Bc= X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS4PR08MB7601 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Signed-off-by: Mikhail Kshevetskiy Reviewed-by: Simon Glass --- net/tcp.c | 74 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 33 deletions(-) diff --git a/net/tcp.c b/net/tcp.c index 37dda6f84f9..0778c153aca 100644 --- a/net/tcp.c +++ b/net/tcp.c @@ -535,10 +535,41 @@ void net_set_syn_options(struct tcp_stream *tcp, union tcp_build_pkt *b) b->ip.end = TCP_O_END; } +const char *tcpflags_to_str(char tcpflags, char *buf, int size) +{ + int i, len; + char *orig = buf; + const struct { + int bit; + const char *name; + } desc[] = {{TCP_RST, "RST"}, {TCP_SYN, "SYN"}, {TCP_PUSH, "PSH"}, + {TCP_FIN, "FIN"}, {TCP_ACK, "ACK"}, {0, NULL}}; + + *orig = '\0'; + for (i = 0; desc[i].name; i++) { + if (!(tcpflags & desc[i].bit)) + continue; + + len = strlen(desc[i].name); + if (size <= len + 1) + break; + if (buf != orig) { + *buf++ = ','; + size--; + } + + strcpy(buf, desc[i].name); + buf += len; + size -= len; + } + return orig; +} + int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int payload_len, u8 action, u32 tcp_seq_num, u32 tcp_ack_num) { union tcp_build_pkt *b = (union tcp_build_pkt *)pkt; + char buf[24]; int pkt_hdr_len; int pkt_len; int tcp_len; @@ -548,55 +579,32 @@ int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int payload_len, * 4 bits reserved options */ b->ip.hdr.tcp_flags = action; - pkt_hdr_len = IP_TCP_HDR_SIZE; b->ip.hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(LEN_B_TO_DW(TCP_HDR_SIZE)); switch (action) { case TCP_SYN: debug_cond(DEBUG_DEV_PKT, - "TCP Hdr:SYN (%pI4, %pI4, sq=%u, ak=%u)\n", - &tcp->rhost, &net_ip, - tcp_seq_num, tcp_ack_num); + "TCP Hdr:%s (%pI4, %pI4, s=%u, a=%u)\n", + tcpflags_to_str(action, buf, sizeof(buf)), + &tcp->rhost, &net_ip, tcp_seq_num, tcp_ack_num); net_set_syn_options(tcp, b); pkt_hdr_len = IP_TCP_O_SIZE; break; - case TCP_SYN | TCP_ACK: - case TCP_ACK: - pkt_hdr_len = IP_HDR_SIZE + net_set_ack_options(tcp, b); - b->ip.hdr.tcp_flags = action; - debug_cond(DEBUG_DEV_PKT, - "TCP Hdr:ACK (%pI4, %pI4, s=%u, a=%u, A=%x)\n", - &tcp->rhost, &net_ip, tcp_seq_num, tcp_ack_num, - action); - break; - case TCP_FIN: - debug_cond(DEBUG_DEV_PKT, - "TCP Hdr:FIN (%pI4, %pI4, s=%u, a=%u)\n", - &tcp->rhost, &net_ip, tcp_seq_num, tcp_ack_num); - payload_len = 0; - pkt_hdr_len = IP_TCP_HDR_SIZE; - break; case TCP_RST | TCP_ACK: case TCP_RST: debug_cond(DEBUG_DEV_PKT, - "TCP Hdr:RST (%pI4, %pI4, s=%u, a=%u)\n", + "TCP Hdr:%s (%pI4, %pI4, s=%u, a=%u)\n", + tcpflags_to_str(action, buf, sizeof(buf)), &tcp->rhost, &net_ip, tcp_seq_num, tcp_ack_num); + pkt_hdr_len = IP_TCP_HDR_SIZE; break; - /* Notify connection closing */ - case (TCP_FIN | TCP_ACK): - case (TCP_FIN | TCP_ACK | TCP_PUSH): - debug_cond(DEBUG_DEV_PKT, - "TCP Hdr:FIN ACK PSH(%pI4, %pI4, s=%u, a=%u, A=%x)\n", - &tcp->rhost, &net_ip, - tcp_seq_num, tcp_ack_num, action); - fallthrough; default: pkt_hdr_len = IP_HDR_SIZE + net_set_ack_options(tcp, b); - b->ip.hdr.tcp_flags = action | TCP_PUSH | TCP_ACK; debug_cond(DEBUG_DEV_PKT, - "TCP Hdr:dft (%pI4, %pI4, s=%u, a=%u, A=%x)\n", - &tcp->rhost, &net_ip, - tcp_seq_num, tcp_ack_num, action); + "TCP Hdr:%s (%pI4, %pI4, s=%u, a=%u)\n", + tcpflags_to_str(action, buf, sizeof(buf)), + &tcp->rhost, &net_ip, tcp_seq_num, tcp_ack_num); + break; } pkt_len = pkt_hdr_len + payload_len; From patchwork Sat Aug 24 09:27:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Kshevetskiy X-Patchwork-Id: 1976365 X-Patchwork-Delegate: pbrobinson@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.a=rsa-sha256 header.s=selector2 header.b=jv6QVX2w; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WrWph1qTmz1yXd for ; Sat, 24 Aug 2024 19:29:00 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id C263288B9E; Sat, 24 Aug 2024 11:27:42 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.b="jv6QVX2w"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 9F0F988C53; Sat, 24 Aug 2024 11:27:40 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,SPF_HELO_PASS, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 Received: from EUR05-AM6-obe.outbound.protection.outlook.com (mail-am6eur05on20701.outbound.protection.outlook.com [IPv6:2a01:111:f403:2612::701]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 21EBC88C91 for ; Sat, 24 Aug 2024 11:27:37 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mikhail.kshevetskiy@genexis.eu ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=ArnRV4FX4yl2gSQN/smjHyxSNNUp91yidICLGhwKt63fV1TBbQk4ZD9W8p9J1XsuKx0pUMhPVH5Qx6Mw1+sKbp1hH5VhnmYIAsiuVIIkJBSk3Qc8RrfjKzK/81vIVIg3YsNJ3OAX4sSwIn5RU081tzNFkEimVc4+ejBIR362DFoRvOEE5zrFc+VEt7vGDh5GG6Fhq2vnR1hljjEFNrNE5n+m4+iQspHVrwdnLWQKTREmGYteW8n/0MSFYURb78MoydEb6i3ryObqNLinLW1lWm2JWO9+5/QJWIxaw58Ih4QZZQYPTBzqQQUCPg6rM1mTHAl+bMxgie1q/cG/spaPqA== 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=PWte4Npgwwl3uVnFvLSqrXyVvO8rK8YKgvcN3Pka8HI=; b=q7Jezoi3oWHN0sS3BLmerpINeOPzR4eqjuewba1wT1ygRsmPLiuX+P2CGfQWfEceZjtTZq8Vr2+mV1Mvu1lJAUkcl9Y012f8F8rpS3n9owqo5oFsttrNXwqfa/3U40gHOIQdDxNaGyxBI8A4h5kmNogrTomwVahoRdkX9C6PNN3LZvIc3cpTGSC/kujxrkwUOZMDnXCZ081EsgyVmI+INZCkekU2CUGuAMzfFtK5rD1jfE9QNx5UmPI7JI7iGABIkZuTS7yB9Lj94vLhIUqo/w0LJ4buU3yq/q7XoUMpP5Xrp+PsvfheoqNzkw8FpU3nRnPE9ogFAxExfCYQRJOyiQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=genexis.eu; dmarc=pass action=none header.from=iopsys.eu; dkim=pass header.d=iopsys.eu; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iopsys.eu; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=PWte4Npgwwl3uVnFvLSqrXyVvO8rK8YKgvcN3Pka8HI=; b=jv6QVX2wF88we2+gr5QI/IG2woPCNp0Gubxez1OS4+2RJDtMium+wQ+FxUhbWscaQ5ntjErHBx0zNizqifiNb/BNaf7e6T8DbKPSf8aGzVCbrETIm2RTHmgdgRe09LZYtCfik0bcWavDIDSwj5foZVJ4+uSRG9JRYk6xIOohV49UHCYEFVM3tSqRyALSSdZPYnDGS9UVGkbEqQgQuDgkCH2YJP5W4TjFGDpvMhiZcYTePP1XiXZGM0nPbgKmvesPvXoQEnl0tch/IYmgFry/ftuiUtUGg5fCFWOX+c01mWy/5APICaj1M5kD1IT4WwWhzP1XpBT3VMdytUe1mOjUQw== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=iopsys.eu; Received: from GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) by AS4PR08MB7601.eurprd08.prod.outlook.com (2603:10a6:20b:4ff::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7897.18; Sat, 24 Aug 2024 09:27:36 +0000 Received: from GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0]) by GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0%2]) with mapi id 15.20.7918.011; Sat, 24 Aug 2024 09:27:36 +0000 From: Mikhail Kshevetskiy To: Tom Rini , Joe Hershberger , Ramon Fried , Mattijs Korpershoek , Simon Glass , Heinrich Schuchardt , AKASHI Takahiro , Michal Simek , Francis Laniel , Anand Moon , Mikhail Kshevetskiy , Marek Vasut , Ilias Apalodimas , Masahisa Kojima , Sean Anderson , Baruch Siach , Yasuharu Shibata , u-boot@lists.denx.de Subject: [PATCH v5 08/11] net/tcp: define a fallback value for rcv_wnd size Date: Sat, 24 Aug 2024 12:27:13 +0300 Message-ID: <20240824092716.1042696-9-mikhail.kshevetskiy@iopsys.eu> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240824092716.1042696-1-mikhail.kshevetskiy@iopsys.eu> References: <20240824092716.1042696-1-mikhail.kshevetskiy@iopsys.eu> X-ClientProxiedBy: GV3P280CA0011.SWEP280.PROD.OUTLOOK.COM (2603:10a6:150:b::7) To GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: GV2PR08MB8121:EE_|AS4PR08MB7601:EE_ X-MS-Office365-Filtering-Correlation-Id: 845884bd-8ce4-4d74-d824-08dcc41efd6a X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|366016|376014|1800799024|52116014|7416014|921020|38350700014; X-Microsoft-Antispam-Message-Info: aGz5/Mrh07GNzQjKwwqGJ1WfVG1tB672tpIc+caRlALH/bJF20jbxOrJNcb+Yv/wtFMrTtrlgqo1ZGeixkulr707ymtOch9s2IIeOKGbkQ60IY7d9ZvPKKuSRrEliBkMlq/EsCDCTLD5uq+phpRg3Qhw4sLGfEqOXD1smQjiv3KZim9btyY30FRU49reqfne+MO+IAwTWvFupCJmLBCa9Cy1qrZzRjGB8kxK69KaLTDFGzyrG5DXmWfKIPDzZYo7ueP7UOweViiT7lX3q2LtpDmgVLSzMTcjVP0hKpm0+aiOsrWOSWsCuoo57pK2KSEtfXmIhDC+x5JV7D+vV9ILtCHZkbu+ewPi0ZK0glv42gUQgg/N1IUIKG/Z7q+3a+oY/yYSi2PtV16iRtmBMXXuKnejG5KwpxKMN+gGcqLNS0QHjGRItM0hiJlIO+ForIkbNMzwUeBfKUOrknMCi2oNh0aIIMOxyaiA/7CQlc/TSKMFE5l7yCkhFron2tj0sX7FyuJ7tJbRHhYsXj9MyTUEOkOgmIisagEYxomseu665OJf3+VTSa/7ldTzDxD9ktmbwmyeIFM8VksV7OtHlDV6yIOVeZ+6kdbXkyt6CEJRKx4eU/5PqSvklWTTBCOfPAXpvUHaYFUC7dWzF31ijjL8/dRSg+hQsY5GYVVTsg9YrH6Mgsry0gkfdfveywi2WLBIg9feI/h+Vcv2NXMlu+00HFq2Cy7C4O3rBoweswtb7ZOJCHBImDOOVJR8nPefA8B9jC9VnYNmg08hbqZeMLXe+n78Tnj/aXRsc+aLtMK4uk0s/s6UxxcVPbsE5Rw+eAT3cZ6ews1SG70iKfQfEJlpDp3FpSJpGFbllMxdiqVtwLjLaIHvJQNC1bKbc+VEpsMYxpv03Hdq8yEFc9ZwnwWA0y9RRpn5yhfBPHOL7FLeAWQskgZBrDf1bhZ0M5NaSns3FleHmGbtUaH1+Ydd7wfY5QzXv0J9CbbnyDG80K9+ZROdpMoEZsPA3w1ZDfMNHGz87SG+4nPQ5hXsQ5FbAYJjhrKX5vyO3b1eU1brpY/aOLcKO22FjjR1PdJIqbDzZ2wmucf3dlvh0RvkXnn/soiIZb6YlhIf15ttBWhIUhLaAcfUNLCApd0xX8PluJ4BnICAA9ALRUVxZ9oXtqgUbACxvNMupjLNcMAqnVtwkGb8LaN9sBatmrYCRVP7iSOotbOl6vOK1P/BoI/hncvGkAYkcvrrBYBXJhmOqiZI8jtSTQEWTf/b7JpJbJmoPXkVEdASYzFLa+QSDOhSzOj+oSRAruGviTbpGv0tcNy1kGNPiexKDJJNDmHQzQ0hpwmpub7c+557qm0+nXuNo0YvUjg+JPf1ARyxj9VXJRZTK1VaUILyZHvnjqhi6p4CGABYdqrhy4yXsg87yjgs1wn5l3B4Kb/1IVaRL/dtKr9J4cEjUzg= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:GV2PR08MB8121.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(366016)(376014)(1800799024)(52116014)(7416014)(921020)(38350700014); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: 52s7x5X/6KHNd2/Y77kc4HwsYU7O1CMm7MD3nEpsiPgRkn6jiSnSPsqyaezlZAtCbtyzhT7V6MfOuLjmcfzt3PS3Gwx6ulwam83feOjbYrv5QpXBCMxtO83C59HkCvhPqLHhsUnQXFEtp1ZdDZM5JivTSdPqQ7+V5vj2BXkGdCu3Ombw5Q8+AW6gttUQ+gPJW0waDdM8rPTPaHzOKuu91i4VdxXrM+yqX82DQmLYSjuvtL+RlQi5g6CO8vz/bqhkjLj8WUZyP290ErOp658nZFmjoLNKlhO1JjTkFXGP6EujswapF7dB0QduzrI8bLxrU8GFW5FU2vnbBHeCOfAxAXzzKHY8TJPQohq+ygrvfYclSIBCZ3Uv/bFpMy03VmuRwgfrZNoIFjI/w0az2+Szt30lck8Mai6XG3QDlAgi4MfesE+T4v175nmnh7XM8jSMV2dx+EvosDgHM+XjC/WfPqRUwWjeTFhEI0mctQzm1l4OTieI+c7VGVLD3tGSdzWffszp53G04L7V6S/b+vuPKInUcT8w472EUlT51YP/pbsA3Owi9G2rSUJvtJZNRAhTLlAVVFy3/Ez1PIPFgIB2hNaVl3WfLkokPugZs0R6RdhsjM8MB6tgh9g7YngxVkBtbVo3Ud7qTpiuRsGA5plZwTrH4z3xqfSqF6bDj5y0tIe/1mrwKcLC6tU6XpoY38/DdvgDZf7o9HDbD9efB0V8EcJAsqKofUfJBbXwKmkAS0A7xsDLOL9IXf1XKI0xWOrQ+YBWMdd9Ze9JWRezl2LJhEdNubJbmMjxVj1oqq5r3+ASDVIzh2L4bf3HWEGMrdUon3O3+2Br7bJZFEsrgvuqYzsPYcRrUZQBf8FaJoRusXkGtmMqXY2z/GDV4Uj09Aw7lTMEyNX0nmYMUu5w/CVLpxJT7ytlw6rPGUsyEgzCoq9R2DqAYSYoUZmoUsUoa67FADGJEBGfHK/TdTwkJlAnE0D4eIz2TW8ElL++dJTA2/yyg1WpT2cTzHijxwnWQmFrdpkMatKxCW2Vuj2XvPFZajJ9GirpWWx6R5a7rc5nzp9jNlxnSFZlRdROApowhbbzue5AhkKTe/coKddxN4tXbOUIKqbeu+wbigQD/b929A5WeeuGfPqvIDLsFR7kNh8uOpc1SdsRHsp6Ggkkm5X6MNJapc3CEKimdGgN259L2oxSmStNHPahSJrUJjomksQ2O+Z9Y9i9ak/iPITBUcmtMfuIISqzzSxt1dgN9F4P1kUjklFGFs9XgryqE1aCDgJ8Cs2XqBVgRyY9zKHYE4yhBuFykkuNLEp6TC4KZO2xqTY4ETFw1X9o/oIkt/4uG4jvOXZpZ+QHMKAqRrrn+DnUqpVtJ3d0iikkEan2xNCNJ/auK3Hh87oJFluQ7c1ZqaWUCP0/dKMwq3KOm/BnUdCGleD6u46qtHG/whpPryrv6WcvmR0AxWH+oRFqDMMf2+9aE2RApqyIxUUVXz5VlzWN1AEhKvx2u2BncqFYe1vqUAfVWoUdm4dEsFnm2GBRLTlD4PwfgndfKy5WJS06EJmcGdqpoQr84v8dgPWr+GdEJkqRVk0FHkohWHPzPzJwd/yeQOakNvi+lzo2R7Fe0Wa+WcABxtXPjO7l3Mv/keCBZw8= X-OriginatorOrg: iopsys.eu X-MS-Exchange-CrossTenant-Network-Message-Id: 845884bd-8ce4-4d74-d824-08dcc41efd6a X-MS-Exchange-CrossTenant-AuthSource: GV2PR08MB8121.eurprd08.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Aug 2024 09:27:36.0620 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 8d891be1-7bce-4216-9a99-bee9de02ba58 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: LtrcwnfjAo74C0FV3+zmPlF+AmsGJlfIkB6noZ99n6Rveg7EjWuoAk33NNbWVlDLYCjK92SYZGkPDlAmTWSs13I9cYz40Ax/QT+bSNaGxfA= X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS4PR08MB7601 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Some driver implements it's own network packet pool, so PKTBUFSRX is zero. This results in zero-size TCP receive window, so data transfer doesn't work. Avoid it by setting a reasonable fallback value. Signed-off-by: Mikhail Kshevetskiy Reviewed-by: Simon Glass --- net/tcp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/tcp.c b/net/tcp.c index 0778c153aca..32ee1fe03ce 100644 --- a/net/tcp.c +++ b/net/tcp.c @@ -36,7 +36,11 @@ #define TCP_SEND_RETRY 3 #define TCP_SEND_TIMEOUT 2000UL #define TCP_RX_INACTIVE_TIMEOUT 30000UL -#define TCP_RCV_WND_SIZE (PKTBUFSRX * TCP_MSS) +#if PKTBUFSRX != 0 + #define TCP_RCV_WND_SIZE (PKTBUFSRX * TCP_MSS) +#else + #define TCP_RCV_WND_SIZE (4 * TCP_MSS) +#endif #define TCP_PACKET_OK 0 #define TCP_PACKET_DROP 1 From patchwork Sat Aug 24 09:27:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Kshevetskiy X-Patchwork-Id: 1976366 X-Patchwork-Delegate: pbrobinson@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.a=rsa-sha256 header.s=selector2 header.b=aJ2XxTq2; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WrWpt31Spz1yXd for ; Sat, 24 Aug 2024 19:29:10 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 2AA5388CE9; Sat, 24 Aug 2024 11:27:43 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.b="aJ2XxTq2"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 1729688CC0; Sat, 24 Aug 2024 11:27:42 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,SPF_HELO_PASS, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 Received: from EUR05-AM6-obe.outbound.protection.outlook.com (mail-am6eur05on2071b.outbound.protection.outlook.com [IPv6:2a01:111:f403:2612::71b]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id A078988C10 for ; Sat, 24 Aug 2024 11:27:38 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mikhail.kshevetskiy@genexis.eu ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=O2oeXgzyHmoqFmeLQwjklhqrqgJQgdy1aXVesNtsSr5oBzRnK+zd3QufPLySYLi1AcMfIPOOLzisiZYViguMUzY8urGtrhkpdE4a1pGeeA+QciL75HPYoVOOQkMriY8UZEkU9ActrUXWHLeyixwVdZZHDW/3I95V3XNE32TNy0tI4vCDxUCgUHR1p8wf6gD7DpCOsqKpXkjyExPcUPah/tNtrD26GSmPJPMYv7H3ii1qRhqvySIAx4fF/DXODa8CjBSUq4uVxdHbvgFMyAyKT9lSwBe7qf+Ox9zPDC8n4HgpLFueM7ecQF8lOHu7Ww2qGJOFs02VFjwOcKmIMWFqJg== 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=MhDrKtJGhb+57TxmjG38iyVs/9AHNELy1ePL2KzWXxA=; b=zH1NPEkSsRx3B9e0tyYYFHQSE6SGcdTPVk44sATwNwubMRBhllGE6xsjnnBKcUXiAycpwwx0VRPcNc5WF/bUNm6ZpgxLgfzO4yQ+3ljO2jl9DTxC00kIEwWzuGbe9s0GuDbVjpRSPzWGtWrHy2EDIrhV5BkYY3ZPvbEeqsZGwfT0vhKmsks+WdU8YdpkHYBJ3S/0TJPgPHuAq/Zl6ENBVNQCEDZ4/2ps5UE4dPDuYh+DVG6X0AcvAIWKRA++UMRx/z1ij2roI7MFQ1nxo05vygfulvtJoybuSnGkJwD1QFZ7TyHQhzuU3cocik+9VSu5SQizcHawiBpc2BzofKLs1Q== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=genexis.eu; dmarc=pass action=none header.from=iopsys.eu; dkim=pass header.d=iopsys.eu; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iopsys.eu; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=MhDrKtJGhb+57TxmjG38iyVs/9AHNELy1ePL2KzWXxA=; b=aJ2XxTq29908BibcxGx3Nrt49zM/aIeSItjO8MH20K2HiE0A8G0XCTU/O+EUh4ElFbr/S5fYLU74IzL2HZCnuJvAdQMgvgNLgYM0HMklEeGT2OViXzHhXfgSgQdejikKTEFCla+i3J4TD33PXKR59ty5zK2vpWzErp9sRul1nmx9EKSCfY51Zw5jQ383hDtuS3JGGjXcoVH0aFAftzfeNBqQ64i07glYSvGpOnBXyvOO2YEf84KHIQCl+ffh4VIPMqhVoVFxYO3GNhGtI0S14a11RJ0NK1lh1/1+BS6VQATQq2mwPApxN9YSV9EAYa7fXKiOsgrz7qHGz/wmGLX7jQ== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=iopsys.eu; Received: from GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) by AS4PR08MB7601.eurprd08.prod.outlook.com (2603:10a6:20b:4ff::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7897.18; Sat, 24 Aug 2024 09:27:37 +0000 Received: from GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0]) by GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0%2]) with mapi id 15.20.7918.011; Sat, 24 Aug 2024 09:27:37 +0000 From: Mikhail Kshevetskiy To: Tom Rini , Joe Hershberger , Ramon Fried , Mattijs Korpershoek , Simon Glass , Heinrich Schuchardt , AKASHI Takahiro , Michal Simek , Francis Laniel , Anand Moon , Mikhail Kshevetskiy , Marek Vasut , Ilias Apalodimas , Masahisa Kojima , Sean Anderson , Baruch Siach , Yasuharu Shibata , u-boot@lists.denx.de Subject: [PATCH v5 09/11] net/netcat: add netcat over tcp support Date: Sat, 24 Aug 2024 12:27:14 +0300 Message-ID: <20240824092716.1042696-10-mikhail.kshevetskiy@iopsys.eu> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240824092716.1042696-1-mikhail.kshevetskiy@iopsys.eu> References: <20240824092716.1042696-1-mikhail.kshevetskiy@iopsys.eu> X-ClientProxiedBy: GV3P280CA0011.SWEP280.PROD.OUTLOOK.COM (2603:10a6:150:b::7) To GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: GV2PR08MB8121:EE_|AS4PR08MB7601:EE_ X-MS-Office365-Filtering-Correlation-Id: abc1a702-a72f-429f-27bb-08dcc41efe22 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|366016|376014|1800799024|52116014|7416014|921020|38350700014; X-Microsoft-Antispam-Message-Info: l3S9bLxUlUhkGPAK5wYCW7WcM+h2OLIclep6qv3Nxiv3ugqUiqkDYsI4UJJ2MQlAhPirHe1OwJHLGqPKTNwihXsfUif9mDyFX7jLmga1/w+55GdoYR0pfo0dDHxVt0AXFH8TOA/AJ17Lhg8Vv1er/J4m2w/xfFf3XKbmSfZW/B5lnogeA9clwOqCUaF54RtPnQ57L/+rVbZg3a51kd7crtd8+wDjdAKZ+3qPl6VNxB4TYquOLVJ7JgP2a0JAKF/fKDzNYuZXYTFOROIkFztTZ5NGxYSIwrzRaWLCl3Rh+hDDKo+MXN6XjY75A44MJXdeeFKnr7UEYrIKAT9YZFdJNwwD/MgZP6zFarbfyaMhfqhMv+1mluduFP1u4rYYeLL+zu0rtsAzSUNqmLzdJ1xR86IM84egR0mT2MtRXcf0nzH+hE91YWOH085Y/5idBHqE9dXDSKUlsduyn3Ih13VSg3azXqGtmRSEA4VT4RMgl/HehsrvT8I/lfO3bOH8PxkXwRiQ8G1XYNcAdOxtBntBrF1ElgZi0yx0c9IMo5sbDKZRmUJHIaRj1vW3RtMKjkfD+8OzHdPzDJQUuUXD+RKG16wjyDGpCFUOV9g3yXbZbJ2pKtUF6QlSnocpKZFxkFH4ikGs11saUUr5eq+dPKJaYjf9DZ2U1F8KJ7kxu/TLEVg4cOdBi7FcOC41LdiCepPTgS/Sp0CwBN7qlQI++qYuj6kJbfSglPr5BIiavOBkdEns621Pl7EFQkqF+l4nAOAsRbiVOHOooqUEcPMqSL2FPMJ/x2ZUm6qC8bBLQI3cJy1gCgLvbcnO/7Nj/K+veJuqPmOr2kSucYpwiehSZe5vRUQt4a9xy+QRQpzpGtjl05cJikrzzXCKqtMd3gZ1Jg2BWPZPH3H+Yx3PkAjhgwURXgWYM5Q4kMWgEz+X0tPqlioYp//KwSiKChfIWcjvsXVHb/eJhemmLhhWeY76wVen7XXFEabryhfBJ+HKJEcMgUEre+HF6DcJFskTEr3O+mZZKsVyN9X6Jq64oK4ZfY3INrN7lcfusdHWaAV2KFTq/Bjodui8KsaccFroz48rZiAFrJpJ/vzljun2JODWsmzIiS4rG+C1CN30nQj14/4npbgKRT8+7F62F0TvPXg5tlKIlsnj0EqO+nPBdb5Tlr6npPft/nC/jC6Ky5rlF24Mn3dwCahgjFPMA/E2CigQcguYAQ1BX9HblsAozf3mvJPoRXP8jtF1Et3jKd7mMcYZdOkk3V5LhhjcXcs2bUq2zNA2hyvM6VIUqzdhdaoyO4K56o7mKoFI+jyQDDOrjAiF69Fk06ctiFO4AJRrH7gW9kGEcDL5SYtEjdSwWsdEUwhNZhDmF9+lYJIB9mLqcDqqxqZp2PVwb4CIEZpsL4B1spN3YKwa8VrHZPICUQtu4jXqlQl3qYxtwtZTq4rgxPurCIA= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:GV2PR08MB8121.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(366016)(376014)(1800799024)(52116014)(7416014)(921020)(38350700014); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: tOy+CTqmcEYkIOKioebbm+/N1VvYrRFqGkW8CYwHPXkhc8Zxe3YJBaSR7LLNdw9t6I6JzNv4i+auZ/3b55U1jYsYUGXaIiJr706K5LUfZeH0/ZEykYMqDEM13AdM2NhzaU/wMCR6GmLhsfJLdSdjGsOZKZcys0UmPWgNdsNr0l264MEjqpY7ppPfLK8dIKRT/oOj/4yMMvHb0xGvbYnEQTS7EJgpMfOhpDQrN65BSj4neShH7UZQ5Gh6se3xPoMrObawY7823UUxf2Y7NB6SekJwNXPvD73w+Zqkyh9E+ib/fngRAzNXnDquttvTc4ylj5v3f6x27KkhHVReV+xBV2h0EW9p0T9QJadOGuiaeYD+FczXw43DDHND2y/tZBNWQWp8sGzAZ29kVtsOVHe4gh/y2ypkG5Pk4+ecMPTfuu0cCivxN0qTLpWiQWWYfMO1of3JZH5meKfrJJVJr5iHZeBDNMSsCztgy2nrtKu52zEFSed+Um5eMIlUzUTBy/kkWB1khXAMy0Dql3XDm2GXXwuNWOpx0oPh3WvYVZPMDdjCW9dkgA9bsUT91J499blPZnPwsz1nsmy97fQ6L1rimUVTF8yfpcVU7oa79H5dYo0fo8oavEHDBvx29Kxt0QErb5l+3PhEimOEqlBbgRwZ9LNURdxW3aZmCmXxJ4wbK4uly3A4NM8fyf66UPBSiJhdM2HnPls+MJCheluAWDT0x9jpU7pcUNjrMroZ7DXrqAe4Qj8p9vQCMfpN/m0v2rZmuInyQmfGkVdvJd2RpCtD6gOkeOi3CT4cJ7MMHN/hs9QHn9MfL/hIKH55aqdznThB6zuqCiQYYento5Tqxmi8/heyXn2SMyJ1mw6BxblKy3QCGLqokAzLMYJ0WNhJJ2cw7QmUaxJd1/97z2pPHZIuPoZeJfLweuobrue95RQyyeCebg5kIDxzY6AESbdmEsCBEUiF7wRyC0uHXxtOssUJFzq2hbne65rsb/sJfkqFfBSqVHmILoD1JFYR4N83L5WT3Kcy+XUvei0GQHU5Yw+aZpYdZRQolv0upJdhND8yUID7Ts5GahWRrJ7UJq3tn/vc7CIUS8F62pHZs9NDN1y7Ss5RES1SfwCcmgVIxNLVCwrqQt4td/F7DRfPOUeAdEE873xcgKqru8hkZnkwSLuhAoWRhKwoMZLcS6fmLLyRypaKUoPUDCvToCtnIm7NXYlv4ncmOo2eFkGvh+0Pn5DZ6MAPPhJBPOdkgF7CCSdcBaofH+F0nn/DxaThDcZedRmtYJlp8R5X++uv0ikEB9Bmw1B+gCcj3v10qqaQfLmJ/mlrvNe0YwzkUDWZBYNv6dOrtX0vwVMeF6NOhUrZbFmMeYdgNB8UCSDXezHARooVfrpxDDlBwYsar5tbNHUhVRhnTvYaPu2tDiIQWIV6v6a/vHjCn4FUDcS3Ewco28AaW/B2x7Q22EWBYD4M7i1Xo71VOC4D33tK+LLLbEgMdvZbLQOuZYqK4gnrHNnne7Cx2HrEl5qudzB5sCw+UoOaYDnLnhIfOq3cnv63I0qdZfpbqfmIF9LVILSLQ8cSU7hcbrSIqO3oBv2OFDQ5VDzZ85M/Ee9H2iXRv5quQX46uBUbVywK5kRqCX4ts39EbDsu+Ew= X-OriginatorOrg: iopsys.eu X-MS-Exchange-CrossTenant-Network-Message-Id: abc1a702-a72f-429f-27bb-08dcc41efe22 X-MS-Exchange-CrossTenant-AuthSource: GV2PR08MB8121.eurprd08.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Aug 2024 09:27:37.2791 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 8d891be1-7bce-4216-9a99-bee9de02ba58 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: YAPDvYTGR8/r6p0pPy98CoyLftFgLRuJsaPevpujXxFKPTnclieX/TCqC1pQ0UQfn9iYZ+LI5TKC0a+0JzJpUO/xtlw2TkqSlh7DAQpjrRA= X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS4PR08MB7601 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean This patch adds downloading/uploading of data with netcat. Client/server mode both supported. How to test: ============ netcat-openbsd=1.219-1 from debian were used for a tests a) Load data from remote host. * U-Boot listen on tcp port 3456 * PC connects u-boot: netcat load ${loadaddr} 3456 PC: netcat -q1 ${UBOOT_IP} 3456 < image.itb b) Load data from remote host. * PC listen on tcp port 3456 * U-Boot connects PC: netcat -q1 -l -p 3456 < image.itb u-boot: netcat load ${loadaddr} ${PC_IP}:3456 c) Save data to remote host * U-Boot listen on tcp port 3456 * PC connects u-boot: netcat save ${loadaddr} ${data_size_in_hex} 3456 PC: netcat -w1 ${UBOOT_IP} 3456 >image.itb d) Save data to remote host * PC listen on tcp port 3456 * U-Boot connects PC: netcat -w1 -l -p 3456 >image.itb u-boot: netcat save ${loadaddr} ${data_size_in_hex} ${PC_IP}:3456 Signed-off-by: Mikhail Kshevetskiy xxx Reviewed-by: Simon Glass --- cmd/Kconfig | 7 ++ cmd/net.c | 34 ++++++-- include/net.h | 2 +- include/net/netcat.h | 20 +++++ net/Makefile | 1 + net/net.c | 9 +++ net/netcat.c | 181 +++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 248 insertions(+), 6 deletions(-) create mode 100644 include/net/netcat.h create mode 100644 net/netcat.c diff --git a/cmd/Kconfig b/cmd/Kconfig index 978f44eda42..abcd003f7f1 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -2007,6 +2007,13 @@ config CMD_WGET wget is a simple command to download kernel, or other files, from a http server over TCP. +config CMD_NETCAT + bool "netcat" + select PROT_TCP + help + netcat is a simple command to load/store kernel, or other files, + using netcat like manner over TCP. + config CMD_MII bool "mii" imply CMD_MDIO diff --git a/cmd/net.c b/cmd/net.c index 53ce2bc5d0c..364139ec5b9 100644 --- a/cmd/net.c +++ b/cmd/net.c @@ -206,6 +206,28 @@ U_BOOT_CMD( ); #endif +#if defined(CONFIG_CMD_NETCAT) +static int do_netcat(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + if (argc < 2) + return 1; + + if (!strcmp(argv[1], "load")) + return netboot_common(NETCAT_LOAD, cmdtp, argc - 1, argv + 1); + else if (!strcmp(argv[1], "save")) + return netboot_common(NETCAT_SAVE, cmdtp, argc - 1, argv + 1); + else + return 1; +} + +U_BOOT_CMD( + netcat, 5, 1, do_netcat, + "load/store data via tcp netcat utility", + "load [loadAddress] [[hostIPaddr:]port]\n" + "save Address Size [[hostIPaddr:]port]\n" +); +#endif + static void netboot_update_env(void) { char tmp[46]; @@ -323,16 +345,17 @@ static int parse_args(enum proto_t proto, int argc, char *const argv[]) switch (argc) { case 1: - if (IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT) + if ((IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT) || + (IS_ENABLED(CONFIG_CMD_NETCAT) && proto == NETCAT_SAVE)) return 1; - /* refresh bootfile name from env */ copy_filename(net_boot_file_name, env_get("bootfile"), sizeof(net_boot_file_name)); break; case 2: - if (IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT) + if ((IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT) || + (IS_ENABLED(CONFIG_CMD_NETCAT) && proto == NETCAT_SAVE)) return 1; /* * Only one arg - accept two forms: @@ -354,7 +377,8 @@ static int parse_args(enum proto_t proto, int argc, char *const argv[]) break; case 3: - if (IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT) { + if ((IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT) || + (IS_ENABLED(CONFIG_CMD_NETCAT) && proto == NETCAT_SAVE)) { if (parse_addr_size(argv)) return 1; } else { @@ -365,7 +389,7 @@ static int parse_args(enum proto_t proto, int argc, char *const argv[]) } break; -#ifdef CONFIG_CMD_TFTPPUT +#if defined(CONFIG_CMD_TFTPPUT) || defined(CONFIG_CMD_NETCAT) case 4: if (parse_addr_size(argv)) return 1; diff --git a/include/net.h b/include/net.h index b0ce13e0a9d..0af6493788a 100644 --- a/include/net.h +++ b/include/net.h @@ -515,7 +515,7 @@ extern int net_restart_wrap; /* Tried all network devices */ enum proto_t { BOOTP, RARP, ARP, TFTPGET, DHCP, DHCP6, PING, PING6, DNS, NFS, CDP, NETCONS, SNTP, TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT_UDP, FASTBOOT_TCP, - WOL, UDP, NCSI, WGET, RS + WOL, UDP, NCSI, WGET, NETCAT_LOAD, NETCAT_SAVE, RS }; extern char net_boot_file_name[1024];/* Boot File name */ diff --git a/include/net/netcat.h b/include/net/netcat.h new file mode 100644 index 00000000000..d8e09aaaa55 --- /dev/null +++ b/include/net/netcat.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-2-Clause + * + * netcat include file + * Copyright (C) 2024 IOPSYS Software Solutions AB + * Author: Mikhail Kshevetskiy + */ +#ifndef __NET_NETCAT_TCP_H__ +#define __NET_NETCAT_TCP_H__ + +/** + * netcat_load_start() - begin netcat in loading mode + */ +void netcat_load_start(void); + +/** + * netcat_save_start() - begin netcat in data saving mode + */ +void netcat_save_start(void); + +#endif /* __NET_NETCAT_TCP_H__ */ diff --git a/net/Makefile b/net/Makefile index 64ab7ec740a..dac7b4859fb 100644 --- a/net/Makefile +++ b/net/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_CMD_WOL) += wol.o obj-$(CONFIG_PROT_UDP) += udp.o obj-$(CONFIG_PROT_TCP) += tcp.o obj-$(CONFIG_CMD_WGET) += wget.o +obj-$(CONFIG_CMD_NETCAT) += netcat.o # Disable this warning as it is triggered by: # sprintf(buf, index ? "foo%d" : "foo", index) diff --git a/net/net.c b/net/net.c index 86182cc504e..d81604a57ce 100644 --- a/net/net.c +++ b/net/net.c @@ -108,6 +108,7 @@ #include #include #include +#include #include "arp.h" #include "bootp.h" #include "cdp.h" @@ -564,6 +565,14 @@ restart: wget_start(); break; #endif +#if defined(CONFIG_CMD_NETCAT) + case NETCAT_LOAD: + netcat_load_start(); + break; + case NETCAT_SAVE: + netcat_save_start(); + break; +#endif #if defined(CONFIG_CMD_CDP) case CDP: cdp_start(); diff --git a/net/netcat.c b/net/netcat.c new file mode 100644 index 00000000000..633afe5c60b --- /dev/null +++ b/net/netcat.c @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * netcat support driver + * Copyright (C) 2024 IOPSYS Software Solutions AB + * Author: Mikhail Kshevetskiy + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define HASHES_PER_LINE 65 + +static struct in_addr server_ip; +static u16 server_port; +static u16 local_port; +static int listen; +static int reading; +static unsigned int packets; +static enum net_loop_state netcat_loop_state; + +static void show_block_marker(void) +{ + if ((packets % 10) == 0) + putc('#'); + else if (((packets + 1) % (10 * HASHES_PER_LINE)) == 0) + puts("\n"); +} + +static void tcp_stream_on_closed(struct tcp_stream *tcp) +{ + if (tcp->status != TCP_ERR_OK) + netcat_loop_state = NETLOOP_FAIL; + + /* + * The status line will be shown after the download/upload + * progress (see show_block_marker() function). This progress + * generally have no final "\n", so jump to new line before + * output the status + */ + if (netcat_loop_state != NETLOOP_SUCCESS) + printf("\nnetcat: Transfer Fail, TCP status - %d\n", tcp->status); + else + printf("\nPackets %s %d, Transfer Successful\n", + reading ? "received" : "transmitted", packets); + net_set_state(netcat_loop_state); +} + +static void tcp_stream_on_rcv_nxt_update(struct tcp_stream *tcp, u32 rx_bytes) +{ + net_boot_file_size = rx_bytes; + show_block_marker(); +} + +static void tcp_stream_on_snd_una_update(struct tcp_stream *tcp, u32 tx_bytes) +{ + show_block_marker(); + if (tx_bytes == image_save_size) + tcp_stream_close(tcp); +} + +static void tcp_stream_on_established(struct tcp_stream *tcp) +{ + netcat_loop_state = NETLOOP_SUCCESS; +} + +static u32 tcp_stream_rx(struct tcp_stream *tcp, u32 rx_offs, void *buf, u32 len) +{ + void *ptr; + + packets++; + ptr = map_sysmem(image_load_addr + rx_offs, len); + memcpy(ptr, buf, len); + unmap_sysmem(ptr); + return len; +} + +static u32 tcp_stream_tx(struct tcp_stream *tcp, u32 tx_offs, void *buf, u32 maxlen) +{ + void *ptr; + + if (tx_offs + maxlen > image_save_size) + maxlen = image_save_size - tx_offs; + if (maxlen == 0) + return 0; + + packets++; + ptr = map_sysmem(image_save_addr + tx_offs, maxlen); + memcpy(buf, ptr, maxlen); + unmap_sysmem(ptr); + return maxlen; +} + +/* + * This function will be called on new connections (incoming or outgoing) + * It MUST: + * -- setup required tcp_stream callbacks (if connection will be accepted) + * -- return a connection verdict: + * 0: discard connection + * 1: accept connection + */ +static int tcp_stream_on_create(struct tcp_stream *tcp) +{ + if (listen) { + /* + * We are listening for incoming connections. + * Accept connections to netcat listen port only. + */ + if (tcp->lport != local_port) + return 0; + } else { + /* + * We are connecting to remote host. + * Check remote IP:port to make sure that this is our connection + */ + if ((tcp->rhost.s_addr != server_ip.s_addr) || + (tcp->rport != server_port)) + return 0; + } + + netcat_loop_state = NETLOOP_FAIL; + net_boot_file_size = 0; + packets = 0; + + tcp->on_closed = tcp_stream_on_closed; + tcp->on_established = tcp_stream_on_established; + if (reading) { + tcp->on_rcv_nxt_update = tcp_stream_on_rcv_nxt_update; + tcp->rx = tcp_stream_rx; + } else { + tcp->on_snd_una_update = tcp_stream_on_snd_una_update; + tcp->tx = tcp_stream_tx; + } + return 1; +} + +static void netcat_start(void) +{ + struct tcp_stream *tcp; + + memset(net_server_ethaddr, 0, 6); + tcp_stream_set_on_create_handler(tcp_stream_on_create); + + if (strchr(net_boot_file_name, ':') == NULL) { + listen = 1; + printf("Listening on port %s...\n", net_boot_file_name); + + local_port = dectoul(net_boot_file_name, NULL); + } else { + listen = 0; + printf("Connecting to %s...\n", net_boot_file_name); + + server_ip = string_to_ip(net_boot_file_name); + server_port = dectoul(strchr(net_boot_file_name, ':') + 1, NULL); + + tcp = tcp_stream_connect(server_ip, server_port); + if (tcp == NULL) { + printf("No free tcp streams\n"); + net_set_state(NETLOOP_FAIL); + return; + } + tcp_stream_put(tcp); + } +} + +void netcat_load_start(void) +{ + reading = 1; + return netcat_start(); +} + +void netcat_save_start(void) +{ + reading = 0; + return netcat_start(); +} From patchwork Sat Aug 24 09:27:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Kshevetskiy X-Patchwork-Id: 1976368 X-Patchwork-Delegate: pbrobinson@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.a=rsa-sha256 header.s=selector2 header.b=zBmJoJjn; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WrWqF6lFMz1yXd for ; Sat, 24 Aug 2024 19:29:29 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id F168588C7C; Sat, 24 Aug 2024 11:27:46 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.b="zBmJoJjn"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 2C072888D5; Sat, 24 Aug 2024 11:27:44 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,SPF_HELO_PASS, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 Received: from EUR05-DB8-obe.outbound.protection.outlook.com (mail-db8eur05on20702.outbound.protection.outlook.com [IPv6:2a01:111:f400:7e1a::702]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 2E02288C53 for ; Sat, 24 Aug 2024 11:27:41 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mikhail.kshevetskiy@genexis.eu ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=xO/SBvAyRXVwgsLzg0d53nLaCOFhrpatm9EQwketlc4CS3vg9LATKkHKaCtc1fSHRIFX/lr/DwrvZP9fws/798xiSiVqNckuFY3VZHGSFeXxGyKJ4yxGXd7sxhcYM+P2iPPibpoaC+tW7QI83EtsdYU7N6doYmneRnuhhpxL8mzh6JfY/V1qYIvPp/MuTU9llSXChjb5uDG8k5FDG+jdj1lGTacZIsqIt4ph2QJOYqaEKz3mB9Ez93cKfn9nj3OxW9nnGgfMH0NzMmTjfo/RyUTTcaTNgVQtj4rHoMBcYibMRUDJoFG+YlPTFihGmTcaTnpRMdt4XSHljqAWbjN9Zg== 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=VhwOxvBlcDYM5Mlz8B4oX9N9X3P/WY70hcpc+Yw+tDw=; b=le6nmLVEthesJTjueV9m1zs4fLfj2ShxMpR1Kqs1Nct9dCrNf20UNlbWLmTz6qF6Ex3TI93fnDbEJ6uJJlZfiN41wk1bn5XP1DLdPXiyvDy1/9TV0fcsJWkYNwwoIAU1cVjIceLfhUMwptmnH1YvdhjnMIzh9Z8Jxu9n98pzMg2NdRt8ei544mrf4F9Tuk37/f3wXzkpL0YnjYrInQKmBADhG8b8pX9oajWRDuWUfSbiAOhVnFtd7F7/cSH9bq9Rpj9wG2knfYNI+oqiG6CbsseQcebiONB4DzDJndDxktVm00+LkBcSvu2PkBVMmqBJMoCUZEWdjsp0445fvPntXA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=genexis.eu; dmarc=pass action=none header.from=iopsys.eu; dkim=pass header.d=iopsys.eu; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iopsys.eu; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=VhwOxvBlcDYM5Mlz8B4oX9N9X3P/WY70hcpc+Yw+tDw=; b=zBmJoJjncJJGZifFZtXB2y9xwVsIO+lkIr3qpTBxprF2QNi2WQ0Ov18TCOhrkL0g/0TP0WzZ0co1pxK+oaVGuTJrM8+hM734ltLuGK/C4+ekMk14AyMsF5X5D3eo7V7IToZPlrV7RHMrF7Ka2PCpIAX8HX6+27SqbdHMr1oFobxL6JbZtsI5ReC0lczMGLMCOb5rgUzJGEglfaowrZfnC2DKkgiy7PfpeJ1w+Syf80Ma4isTUQL6nRxSiR8w4UU7/3FgdtsJaDLBBjkQsx3NFbw5M0H8Q2pe8Qi0UNIocv6Jsytu25Zx0IizTdZcsiA4YDKSlMxDEXHpr3FqK9QaFA== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=iopsys.eu; Received: from GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) by DB9PR08MB7445.eurprd08.prod.outlook.com (2603:10a6:10:36f::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7897.13; Sat, 24 Aug 2024 09:27:39 +0000 Received: from GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0]) by GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0%2]) with mapi id 15.20.7918.011; Sat, 24 Aug 2024 09:27:38 +0000 From: Mikhail Kshevetskiy To: Tom Rini , Joe Hershberger , Ramon Fried , Mattijs Korpershoek , Simon Glass , Heinrich Schuchardt , AKASHI Takahiro , Michal Simek , Francis Laniel , Anand Moon , Mikhail Kshevetskiy , Marek Vasut , Ilias Apalodimas , Masahisa Kojima , Sean Anderson , Baruch Siach , Yasuharu Shibata , u-boot@lists.denx.de Subject: [PATCH v5 10/11] net/httpd: add httpd common code Date: Sat, 24 Aug 2024 12:27:15 +0300 Message-ID: <20240824092716.1042696-11-mikhail.kshevetskiy@iopsys.eu> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240824092716.1042696-1-mikhail.kshevetskiy@iopsys.eu> References: <20240824092716.1042696-1-mikhail.kshevetskiy@iopsys.eu> X-ClientProxiedBy: GV3P280CA0011.SWEP280.PROD.OUTLOOK.COM (2603:10a6:150:b::7) To GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: GV2PR08MB8121:EE_|DB9PR08MB7445:EE_ X-MS-Office365-Filtering-Correlation-Id: f68e9572-0322-4e85-6a39-08dcc41efedd X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|1800799024|366016|376014|52116014|7416014|921020|38350700014; X-Microsoft-Antispam-Message-Info: nWIQhAw4Ql5aKadT9Z6bnic8P50Sg46pGPs6drvHkqWgeDfLYgdE3z1mwiUn1EC4EUhB4TB/f1kIEsftCqmMkRDUeeCSX5zxGuC9tDKeTSNs/E2m6FiLc/UOv4jfkOReLMm8BvBcAHyndIpsOKuIUP9mrom0WOlGz+nNAxtkD4Q6bBmsVryyulNJ/8SoIhRjY0vQoP5K1pmiRToMkpy3G8KMyB9hvC6ziYcsgQeKrcFQpJZRjWPZTv8r41XdtzynvYzRgoOZSU8Exp5puT84w5a8avcI9DBB6Ef3d5T1IiYoK1+GuFQhOgPQDPgIEabFEVEMHDzZMp+H6ch74WtMOGuM57lxYD+dVO/zM2YPGPBmdr/VVZYx39dWrUsy1Hp18Fr5IBSB38A3/FBe0n7OBwadb20J1p0ryN12f2p2lh5Ma9f2hWeDBIM7HolahY8L3SEA47OoyWXI05fPg8J0qQjpfD7WKboIFcyjMhX6ubVKDU3Imy29V6fBzrD3ZMRlcR7Pnv5DLD3wGHIqxrcrb4DxRU0TxCYTrO4BqgpNj/bSv5HVPlX9QDeXXYnOV60vD5jDZ6ErdZ3zfFmuFbpNYPQjpS1OwqrJLtKYFmVyTCHZzv9Jkn5eegZi+O3MnFhOI46LxU1hRA89z6ZDjgySUyQOefBed6CLSyiUwf7jdBykqNDFI2o6ijhIWe0KXMFgWsICGf9xYaCmXgFPDOwcoDlEei6QNnioDf7Dv5sgjmlownS0Q1wrg4U7d9R1Jk24ed3uvSf7oKn8R9OzzK3wEnDLfjwEisnNa3wuXBPc+dTLKvIfPdCydwDw/6jCc3BnRHaqqLHLkMHVmiValmHfnGkawx4TDvoEAZAcNtTQUhznv3XLrwWuQ5syT9xgutxegX/6vV3sYrrUpPDapUKqn1mWY7xIGV8zFktaLbDbkSoy8nMfV8QmMKe34HCU3DKExe+6pqGZyJnuWGtQrrHgIi790vDHdFCqrAwMdPa0Sgq5MKCJlvcEiwWZzAkC4IogWxzCUCkepfm7HSi336LWdjx1ptQqz2Ulmo7uyhlGfvC4bCC9GqrOHIAKaXQtztLHWSoQpAjqhOxcG4zNa+06TfLrUGlOVoXcrGmbPbcHgLAELMseaLHl43r3c+ArUaqws7fN0wXIdWNHtCXjjNM75cUAsKL4owCXBRY00FsgmhvgdgqgFfKxVZzlVH+hN8aaDsRHO5ClqktEjbr8DUoE9RTIp9xMtKXTPv8ememSyNFJsza5ezO9if6/1il+r7K+vljVo/KtHQ5SzaTZdsqz5dlpG94v3UWV1w3Kd3mKjgeO9iHbV4XWDsVqXaH5SosEEwz+nkexGUnW2eR8yvm7odkVxCkZdni3Ze2+nhoWOJDrMkbahV+QVoqSAoUrPXbzcLSZcYdbV00SNxHgD3c2ke0abtQU0qi4ELdY0UWUh6Q= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:GV2PR08MB8121.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(1800799024)(366016)(376014)(52116014)(7416014)(921020)(38350700014); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: EabD80awRGLdWpzCl60mXNdaH1R3oopJRTy/JkuhQ92yLyZP7SbI+D9p35EiZbJJiKTNJ3cRFINxszh3nGP7e/88H/HMB9EvLB3QlxdUYtKayBzYqO+buM2FuYA2sosEks1EJkXCwMVcGpYFixrCuWTmBLw40N9oUohcvTJ0rau5ikp7QLfUgRpHEpG7G39t9bi+N+CtP4ErxBAcBBT5B0hxI2Kpnsk+LTG5I5VHY1f//jZpFxsIj5Zd1foGLrqvSeHeCqBa1yanzrtply5/uEHBmwcd7itTLQlXiuKJrjfwgAWaDWEOhI2xiT5pxK9xf33mo8gTSq+ePOjCswYzKBCdlwN2FF2Z30snhOuz7UoQu4t6nIgTsF7BWtsMzSjFib0tJjGjAX91BAdAQ3cHUALKTmRunH/Tt2nHQ6lm6Nuhg69ULQcdSSEJgvkWppDljn3pIULhLHGCGH+NEDtIUouL5b4ne8Bb183aNzgJz9viWqBtuoEyGpfW3G0ss0FXkYzhNBaj2DEJ0YXglgems3NaQo7uFrJEvMOW9r7eHYY6ssJk67bSB2uELjPJoDtHcH917f8kZDmVXc9ZlaFg6RquTq+IyEgATXjsHrGGN9lebmK3c99C+ZAuySUqBZzEAKjC5YRkueG4AWSadV6Nn0EAHxdpcB7a5ZyghYIbsWtFFpyodWDQebgdd/rd1ouiAjBd3Qj/6eKNhtz3H+UF95x6dQcCdMfUBB8KcskSbwj1HnUBZYl2i8ovuZUA2tyBBaaqF+bXzvdSWmm0F9s7AsaY35L7SVxx9tyEXNp8fpvuUwoTtvazZsqPsndF/KVzgt54ZOg5M3pLQ/NLTRpKP3E68k0bzhZsdW8hrYFLrtRrRI+CSTAV8qfnBsk6J0jd3z/KMwIc8MXl0zAJ4dyTaMKnZgIjQA8o58q0j7KXXot+/Z14GE8omwfGyP+88jNdh832HaEsSfSj//gfqBmfunXcGDfLKR/6UlXsNnbGL7W6qDBkd8ksjITqEZu6yuvT4BturVsfBWrsabsLOxIQR5k3tmLqwUCHmojHgONG9IO5YwCopnvhuWX6cIpydzQN7bK2oI8bLXClC6RP09ecg7djOJCWqQ/rJH/YpWujutap0XjBPFPbzw68SuAXT5+GTcXxMm7TkSkni5aR+hgFFgk2yVWO65eqNf4gb+dR9QpOnLUN3Ekm3OMJkv5PfY309bMnIGKeikhN8ulEp52ZXZbucnJNy7qTuicBCIf4Clfi6+HJgLFeG1vsqbX+J/3Y6c+RDD+9/7uWHxviQ5VwHOs20t1XYtRPQKEpl5w+mxoEj/HW909Sl8MYuzI6c+2FcASbhtkJ2HmdcE702Tebskc5qaoZXzW7hO4L7r7ArXHkECcAjZtG9aRPYgk7kG7mgcN1chS54Vo83rUJKxhoVsSSVsvtSdT7zwpHT7qe8hZO7yFunH5G0Lyk9gYdOfLOcy9uFPT4pEYxpLAvtHNiuwRTCncvddiUA5zL76sZUoqbKBApQrnTo0ZJ4z5ZcGzncaCyTHF+V+yVO7OLwUvmYJQdlDpq3lnwYuzw3WCyVI4Ael2e183RTmGwJ/7k1Il/FiA3wixE/1q8NHX6K9XfC4cyYuZeCyTTjJczVNBAOZQ= X-OriginatorOrg: iopsys.eu X-MS-Exchange-CrossTenant-Network-Message-Id: f68e9572-0322-4e85-6a39-08dcc41efedd X-MS-Exchange-CrossTenant-AuthSource: GV2PR08MB8121.eurprd08.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Aug 2024 09:27:38.5221 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 8d891be1-7bce-4216-9a99-bee9de02ba58 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: yQBAtQJn1T89zBFVPacwYxj9a4cXuamt34UM/jhyTEY4VJcDRvVZOL1vrOUHqfUH/ECr6/C+Jq+frrfeqh791sVzBjxiT7wr3OvR6vDwWBU= X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB9PR08MB7445 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean This patch adds HTTP/1.1 compatible web-server that can be used by other. Server supports GET, POST, and HEAD requests. On client request it will call user specified GET/POST callback. Then results will be transmitted to client. The following restrictions exist on the POST request at the moment: * only multipart/form-data with a single file object * object will be stored to a memory area specified in image_load_addr variable Signed-off-by: Mikhail Kshevetskiy Reviewed-by: Simon Glass --- include/net.h | 2 +- include/net/httpd.h | 64 ++++ net/Kconfig | 14 + net/Makefile | 1 + net/httpd.c | 692 ++++++++++++++++++++++++++++++++++++++++++++ net/net.c | 6 + 6 files changed, 778 insertions(+), 1 deletion(-) create mode 100644 include/net/httpd.h create mode 100644 net/httpd.c diff --git a/include/net.h b/include/net.h index 0af6493788a..154885a2b7e 100644 --- a/include/net.h +++ b/include/net.h @@ -515,7 +515,7 @@ extern int net_restart_wrap; /* Tried all network devices */ enum proto_t { BOOTP, RARP, ARP, TFTPGET, DHCP, DHCP6, PING, PING6, DNS, NFS, CDP, NETCONS, SNTP, TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT_UDP, FASTBOOT_TCP, - WOL, UDP, NCSI, WGET, NETCAT_LOAD, NETCAT_SAVE, RS + WOL, UDP, NCSI, WGET, NETCAT_LOAD, NETCAT_SAVE, HTTPD, RS }; extern char net_boot_file_name[1024];/* Boot File name */ diff --git a/include/net/httpd.h b/include/net/httpd.h new file mode 100644 index 00000000000..ff0dc93ecf5 --- /dev/null +++ b/include/net/httpd.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * httpd support header file + * Copyright (C) 2024 IOPSYS Software Solutions AB + * Author: Mikhail Kshevetskiy + * + */ +#ifndef __NET_HTTPD_COMMON_H__ +#define __NET_HTTPD_COMMON_H__ + +struct http_reply { + int code; + const char *code_msg; + const char *data_type; + void *data; + u32 len; +}; + +struct httpd_post_data { + const char *name; + const char *filename; + void *addr; + u32 size; +}; + +enum httpd_req_check { + HTTPD_REQ_OK, + HTTPD_BAD_URL, + HTTPD_BAD_REQ, + HTTPD_CLNT_RST +}; + +struct httpd_config { + enum net_loop_state (*on_stop)(void); + void (*on_req_end)(void *req_id); + + enum httpd_req_check (*pre_get)(void *req_id, const char *url); + enum httpd_req_check (*pre_post)(void *req_id, const char *url, + struct httpd_post_data *post); + + struct http_reply * (*get)(void *req_id, const char *url); + struct http_reply * (*post)(void *req_id, const char *url, + struct httpd_post_data *post); + + struct http_reply *error_400; + struct http_reply *error_404; +}; + +/** + * httpd_setup() - configure the webserver + */ +void httpd_setup(struct httpd_config *config); + +/** + * httpd_stop() - start stopping of the webserver + */ +void httpd_stop(void); + +/** + * httpd_start() - start the webserver + */ +void httpd_start(void); + +#endif /* __NET_HTTPD_COMMON_H__ */ diff --git a/net/Kconfig b/net/Kconfig index 7cb80b880a9..55739b9bc98 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -243,6 +243,20 @@ config PROT_TCP_SACK This option should be turn on if you want to achieve the fastest file transfer possible. +config HTTPD_COMMON + bool "HTTP server common code" + depends on PROT_TCP + help + HTTP/1.1 compatible web-server common code. It supports standard + GET/POST requests. User MUST provide a configuration to the + web-server. On client request web-server will call user specified + GET/POST callback. Then results will be transmitted to the client. + The following restricions on the POST request are present at the + moment: + * only mulipart/form-data with a single binary object + * object will be stored to a memory area specified in + image_load_addr variable + config IPV6 bool "IPv6 support" help diff --git a/net/Makefile b/net/Makefile index dac7b4859fb..c1f491fad02 100644 --- a/net/Makefile +++ b/net/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_PROT_UDP) += udp.o obj-$(CONFIG_PROT_TCP) += tcp.o obj-$(CONFIG_CMD_WGET) += wget.o obj-$(CONFIG_CMD_NETCAT) += netcat.o +obj-$(CONFIG_HTTPD_COMMON) += httpd.o # Disable this warning as it is triggered by: # sprintf(buf, index ? "foo%d" : "foo", index) diff --git a/net/httpd.c b/net/httpd.c new file mode 100644 index 00000000000..052fae9ced0 --- /dev/null +++ b/net/httpd.c @@ -0,0 +1,692 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * httpd support driver + * Copyright (C) 2024 IOPSYS Software Solutions AB + * Author: Mikhail Kshevetskiy + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define HTTP_PORT 80 + +#define MAX_URL_LEN 128 +#define MAX_BOUNDARY_LEN 80 +#define MAX_MPART_NAME_LEN 80 +#define MAX_FILENAME_LEN 256 +#define BUFFER_LEN 2048 + +enum http_req_state { + ST_REQ_LINE = 0, + ST_REQ_HDR, + ST_REQ_MPBOUNDARY, + ST_REQ_MPART, + ST_REQ_MPFILE, + ST_REQ_MPEND, + ST_REQ_DONE, +}; + +enum http_reply_state { + ST_REPLY_ERR = 0, + ST_REPLY_HDR, + ST_REPLY_BODY +}; + +enum http_method { + HTTP_UNKNOWN = -1, + HTTP_GET, + HTTP_POST, + HTTP_HEAD, + HTTP_OPTIONS, +}; + +struct httpd_priv { + enum http_req_state req_state; + enum http_reply_state reply_state; + + struct tcp_stream *tcp; + + enum http_method method; + char url[MAX_URL_LEN]; + u32 version_major; + u32 version_minor; + u32 hdr_len; + + u32 post_fstart; + u32 post_flen; + char post_fname[MAX_FILENAME_LEN]; + char post_name[MAX_MPART_NAME_LEN]; + char post_boundary[MAX_BOUNDARY_LEN]; + + int reply_code; + u32 reply_fstart; + u32 reply_flen; + void *reply_fdata; + + u32 rx_processed; + char buf[BUFFER_LEN]; +}; + +static struct http_reply options_reply = { + .code = 200, + .code_msg = "OK", + .data_type = "text/plain", + .data = NULL, + .len = 0 +}; + +static int stop_server; +static int tsize_num_hash; + +static struct httpd_config *cfg; + +static void show_block_marker(u32 offs, u32 size) +{ + int cnt; + + if (offs > size) + offs = size; + + cnt = offs * 50 / size; + while (tsize_num_hash < cnt) { + putc('#'); + tsize_num_hash++; + } + + if (cnt == 50) + putc('\n'); +} + +static void tcp_stream_on_closed(struct tcp_stream *tcp) +{ + struct httpd_priv *priv = tcp->priv; + + if ((priv->req_state != ST_REQ_DONE) && + (priv->req_state >= ST_REQ_MPFILE)) { + printf("\nHTTPD: transfer was terminated\n"); + } + + if (cfg->on_req_end) + cfg->on_req_end(tcp->priv); + + free(tcp->priv); + + if (stop_server) + net_set_state(cfg->on_stop ? cfg->on_stop() : NETLOOP_SUCCESS); +} + +static void http_make_reply(struct httpd_priv *priv, struct http_reply *reply, + int head_only) +{ + int offs = 0; + + if (priv->version_major >= 1) { + offs = snprintf(priv->buf, sizeof(priv->buf), + "HTTP/%d.%d %d %s\r\n" + "Server: %s\r\n" + "Connection: close\r\n" + "Cache-Control: no-store\r\n" + "Content-Type: %s\r\n" + "Content-Length: %d\r\n", + priv->version_major, priv->version_minor, + reply->code, reply->code_msg, U_BOOT_VERSION, + reply->data_type, + head_only ? 0 : reply->len); + if (priv->method == HTTP_OPTIONS) + offs += snprintf(priv->buf + offs, sizeof(priv->buf) - offs, + "Access-Control-Allow-Methods: GET, HEAD, OPTIONS, POST\r\n"); + offs += snprintf(priv->buf + offs, sizeof(priv->buf) - offs, + "\r\n"); + } + + priv->reply_code = reply->code; + priv->reply_fstart = offs; + if (!head_only) { + priv->reply_flen = reply->len; + priv->reply_fdata = reply->data; + } +} + +static enum httpd_req_check http_parse_line(struct httpd_priv *priv, char *line) +{ + char *url, *version, *data, *end; + u32 len, tmp; + enum httpd_req_check ret; + struct httpd_post_data post; + + switch (priv->req_state) { + case ST_REQ_LINE: + if (!strncasecmp(line, "GET ", 4)) { + priv->method = HTTP_GET; + url = line + 4; + } else if (!strncasecmp(line, "POST ", 5)) { + priv->method = HTTP_POST; + url = line + 5; + } else if (!strncasecmp(line, "HEAD ", 5)) { + priv->method = HTTP_HEAD; + url = line + 5; + } else if (!strncasecmp(line, "OPTIONS ", 8)) { + priv->method = HTTP_OPTIONS; + url = line + 8; + } else { + /* unknown request */ + return HTTPD_CLNT_RST; + } + + version = strstr(url, " "); + if (!version) { + /* check for HTTP 0.9 */ + if (*url != '/' || priv->method != HTTP_GET) + return HTTPD_CLNT_RST; + + if (strlen(url) >= MAX_URL_LEN) + return HTTPD_CLNT_RST; + + if (cfg->pre_get) { + ret = cfg->pre_get(priv, url); + if (ret != HTTPD_REQ_OK) + return ret; + } + + priv->req_state = ST_REQ_DONE; + priv->hdr_len = strlen(line) + 2; + priv->version_major = 0; + priv->version_minor = 9; + strcpy(priv->url, url); + return HTTPD_REQ_OK; + } + + if (strncasecmp(version + 1, "HTTP/", 5)) { + /* version is required for HTTP >= 1.0 */ + return HTTPD_CLNT_RST; + } + + *version++ = '\0'; + version += strlen("HTTP/"); + + priv->version_major = dectoul(version, &end); + switch (*end) { + case '\0': + priv->version_minor = 0; + break; + case '.': + priv->version_minor = dectoul(end + 1, &end); + if (*end == '\0') + break; + fallthrough; + default: + /* bad version format */ + return HTTPD_CLNT_RST; + } + + if (priv->version_major < 1) { + /* bad version */ + return HTTPD_CLNT_RST; + } + + if (priv->version_major > 1 || priv->version_minor > 1) { + /* We support HTTP/1.1 or early standards only */ + priv->version_major = 1; + priv->version_minor = 1; + } + + if (*url != '/') + return HTTPD_CLNT_RST; + + if (strlen(url) >= MAX_URL_LEN) + return HTTPD_CLNT_RST; + + priv->req_state = ST_REQ_HDR; + strcpy(priv->url, url); + return HTTPD_REQ_OK; + + case ST_REQ_HDR: + if (*line == '\0') { + priv->hdr_len = priv->rx_processed + 2; + switch (priv->method) { + case HTTP_GET: + case HTTP_HEAD: + if (cfg->pre_get) { + ret = cfg->pre_get(priv, priv->url); + if (ret != HTTPD_REQ_OK) + return ret; + } + fallthrough; + + case HTTP_OPTIONS: + priv->req_state = ST_REQ_DONE; + return HTTPD_REQ_OK; + + default: + break; + } + + if (*priv->post_boundary != '\0') { + priv->req_state = ST_REQ_MPBOUNDARY; + return HTTPD_REQ_OK; + } + /* NOT multipart/form-data POST request */ + return HTTPD_BAD_REQ; + } + + if (priv->method != HTTP_POST) + return HTTPD_REQ_OK; + + len = strlen("Content-Length: "); + if (!strncasecmp(line, "Content-Length: ", len)) { + data = line + len; + priv->post_flen = simple_strtol(data, &end, 10); + if (*end != '\0') { + /* bad Content-Length string */ + return HTTPD_BAD_REQ; + } + return HTTPD_REQ_OK; + } + + len = strlen("Content-Type: "); + if (!strncasecmp(line, "Content-Type: ", len)) { + data = strstr(line + len, " boundary="); + if (!data) { + /* expect multipart/form-data format */ + return HTTPD_BAD_REQ; + } + + data += strlen(" boundary="); + if (strlen(data) >= sizeof(priv->post_boundary)) { + /* no space to keep boundary */ + return HTTPD_BAD_REQ; + } + + strcpy(priv->post_boundary, data); + return HTTPD_REQ_OK; + } + + return HTTPD_REQ_OK; + + case ST_REQ_MPBOUNDARY: + if (*line == '\0') + return HTTPD_REQ_OK; + if (line[0] != '-' || line[1] != '-' || + strcmp(line + 2, priv->post_boundary)) { + /* expect boundary line */ + return HTTPD_BAD_REQ; + } + priv->req_state = ST_REQ_MPART; + return HTTPD_REQ_OK; + + case ST_REQ_MPART: + if (*line == '\0') { + if (*priv->post_name == '\0') + return HTTPD_BAD_REQ; + + priv->post_fstart = priv->rx_processed + 2; + priv->post_flen -= priv->post_fstart - priv->hdr_len; + /* expect: "\r\n--${boundary}--\r\n", so strlen() + 8 */ + priv->post_flen -= strlen(priv->post_boundary) + 8; + + if (cfg->pre_post) { + post.addr = NULL; + post.name = priv->post_name; + post.filename = priv->post_fname; + post.size = priv->post_flen; + + ret = cfg->pre_post(priv, priv->url, &post); + if (ret != HTTPD_REQ_OK) + return ret; + } + + tsize_num_hash = 0; + printf("File: %s, %u bytes\n", priv->post_fname, priv->post_flen); + printf("Loading: "); + + priv->req_state = ST_REQ_MPFILE; + return HTTPD_REQ_OK; + } + + len = strlen("Content-Disposition: "); + if (!strncasecmp(line, "Content-Disposition: ", len)) { + data = strstr(line + len, " name=\""); + if (!data) { + /* name attribute not found */ + return HTTPD_BAD_REQ; + } + + data += strlen(" name=\""); + end = strstr(data, "\""); + if (!end) { + /* bad name attribute format */ + return HTTPD_BAD_REQ; + } + + tmp = end - data; + if (tmp >= sizeof(priv->post_name)) { + /* multipart name is too long */ + return HTTPD_BAD_REQ; + } + strncpy(priv->post_name, data, tmp); + priv->post_name[tmp] = '\0'; + + data = strstr(line + len, " filename=\""); + if (!data) { + /* filename attribute not found */ + return HTTPD_BAD_REQ; + } + + data += strlen(" filename=\""); + end = strstr(data, "\""); + if (!end) { + /* bad filename attribute format */ + return HTTPD_BAD_REQ; + } + + tmp = end - data; + if (tmp >= sizeof(priv->post_fname)) + tmp = sizeof(priv->post_fname) - 1; + strncpy(priv->post_fname, data, tmp); + priv->post_fname[tmp] = '\0'; + return HTTPD_REQ_OK; + } + + return HTTPD_REQ_OK; + + case ST_REQ_MPEND: + if (*line == '\0') + return HTTPD_REQ_OK; + + len = strlen(priv->post_boundary); + if (line[0] != '-' || line[1] != '-' || + strncmp(line + 2, priv->post_boundary, len) || + line[len + 2] != '-' || line[len + 3] != '-' || + line[len + 4] != '\0') { + /* expect final boundary line */ + return HTTPD_BAD_REQ; + } + priv->req_state = ST_REQ_DONE; + return HTTPD_REQ_OK; + + default: + return HTTPD_BAD_REQ; + } +} + +static enum httpd_req_check http_parse_buf(struct httpd_priv *priv, + char *buf, u32 size) +{ + char *eol_pos; + u32 len; + enum httpd_req_check ret; + + buf[size] = '\0'; + while (size > 0) { + eol_pos = strstr(buf, "\r\n"); + if (!eol_pos) + break; + + *eol_pos = '\0'; + len = eol_pos + 2 - buf; + + ret = http_parse_line(priv, buf); + if (ret != HTTPD_REQ_OK) { + /* request processing error */ + return ret; + } + + priv->rx_processed += len; + buf += len; + size -= len; + + if ((priv->req_state == ST_REQ_MPFILE) || + (priv->req_state == ST_REQ_DONE)) + return HTTPD_REQ_OK; + } + /* continue when more data becomes available */ + return HTTPD_REQ_OK; +} + +static void tcp_stream_on_rcv_nxt_update(struct tcp_stream *tcp, u32 rx_bytes) +{ + struct httpd_priv *priv; + void *ptr; + u32 shift, size; + enum httpd_req_check ret; + struct http_reply *reply; + struct httpd_post_data post; + + priv = tcp->priv; + + switch (priv->req_state) { + case ST_REQ_DONE: + return; + + case ST_REQ_MPFILE: + show_block_marker(rx_bytes - priv->post_fstart, + priv->post_flen); + if (rx_bytes < priv->post_fstart + priv->post_flen) { + priv->rx_processed = rx_bytes; + return; + } + priv->req_state = ST_REQ_MPEND; + priv->rx_processed = priv->post_fstart + priv->post_flen; + fallthrough; + + case ST_REQ_MPEND: + shift = priv->rx_processed - priv->post_fstart; + ptr = map_sysmem(image_load_addr + shift, + rx_bytes - priv->rx_processed); + ret = http_parse_buf(priv, ptr, + rx_bytes - priv->rx_processed); + unmap_sysmem(ptr); + + if (ret != HTTPD_REQ_OK) + goto error; + if (priv->req_state != ST_REQ_DONE) + return; + break; + + default: + ret = http_parse_buf(priv, priv->buf + priv->rx_processed, + rx_bytes - priv->rx_processed); + if (ret != HTTPD_REQ_OK) + goto error; + + if (priv->req_state == ST_REQ_MPFILE) { + /* + * We just switched from parsing of HTTP request + * headers to binary data reading. Our tcp->rx + * handler may put some binary data to priv->buf. + * It's time to copy these data to a proper place. + * It's required to copy whole buffer data starting + * from priv->rx_processed position. Otherwise we + * may miss data placed after the first hole. + */ + size = sizeof(priv->buf) - priv->rx_processed; + if (size > 0) { + ptr = map_sysmem(image_load_addr, size); + memcpy(ptr, priv->buf + priv->rx_processed, size); + unmap_sysmem(ptr); + } + + show_block_marker(rx_bytes - priv->post_fstart, + priv->post_flen); + } + + if (priv->req_state != ST_REQ_DONE) + return; + break; + } + + switch (priv->method) { + case HTTP_OPTIONS: + reply = &options_reply; + break; + + case HTTP_GET: + case HTTP_HEAD: + if (!cfg->get) { + ret = HTTPD_BAD_REQ; + goto error; + } + reply = cfg->get(priv, priv->url); + break; + + case HTTP_POST: + if (!cfg->post) { + ret = HTTPD_BAD_REQ; + goto error; + } + post.name = priv->post_name; + post.filename = priv->post_fname; + post.size = priv->post_flen; + post.addr = map_sysmem(image_load_addr, post.size); + reply = cfg->post(priv, priv->url, &post); + unmap_sysmem(post.addr); + break; + + default: + ret = HTTPD_BAD_REQ; + goto error; + } + + http_make_reply(priv, reply, priv->method == HTTP_HEAD); + return; + +error: + priv->req_state = ST_REQ_DONE; + switch (ret) { + case HTTPD_BAD_URL: + http_make_reply(priv, cfg->error_404, 0); + break; + case HTTPD_BAD_REQ: + http_make_reply(priv, cfg->error_400, 0); + break; + default: + tcp_stream_reset(tcp); + break; + } +} + +static u32 tcp_stream_rx(struct tcp_stream *tcp, u32 rx_offs, void *buf, u32 len) +{ + void *ptr; + struct httpd_priv *priv; + u32 shift; + + priv = tcp->priv; + switch (priv->req_state) { + case ST_REQ_DONE: + return len; + case ST_REQ_MPFILE: + case ST_REQ_MPEND: + shift = rx_offs - priv->post_fstart; + ptr = map_sysmem(image_load_addr + shift, len); + memcpy(ptr, buf, len); + unmap_sysmem(ptr); + return len; + default: + /* + * accept data that fits to buffer, + * reserve space for end of line symbol + */ + if (rx_offs + len > sizeof(priv->buf) - 1) + len = sizeof(priv->buf) - rx_offs - 1; + memcpy(priv->buf + rx_offs, buf, len); + return len; + } +} + +static void tcp_stream_on_snd_una_update(struct tcp_stream *tcp, u32 tx_bytes) +{ + struct httpd_priv *priv; + + priv = tcp->priv; + if ((priv->req_state == ST_REQ_DONE) && + (tx_bytes == priv->reply_fstart + priv->reply_flen)) + tcp_stream_close(tcp); +} + +static u32 tcp_stream_tx(struct tcp_stream *tcp, u32 tx_offs, void *buf, u32 maxlen) +{ + struct httpd_priv *priv; + u32 len, bytes = 0; + char *ptr; + + priv = tcp->priv; + if (priv->req_state != ST_REQ_DONE) + return 0; + + if (tx_offs < priv->reply_fstart) { + len = maxlen; + if (len > priv->reply_fstart - tx_offs) + len = priv->reply_fstart - tx_offs; + memcpy(buf, priv->buf + tx_offs, len); + buf += len; + tx_offs += len; + bytes += len; + maxlen -= len; + } + + if (tx_offs >= priv->reply_fstart) { + if (tx_offs + maxlen > priv->reply_fstart + priv->reply_flen) + maxlen = priv->reply_fstart + priv->reply_flen - tx_offs; + if (maxlen > 0) { + ptr = priv->reply_fdata + tx_offs - priv->reply_fstart; + memcpy(buf, ptr, maxlen); + bytes += maxlen; + } + } + + return bytes; +} + +static int tcp_stream_on_create(struct tcp_stream *tcp) +{ + struct httpd_priv *priv; + + if (!cfg || stop_server || tcp->lport != HTTP_PORT) + return 0; + + priv = malloc(sizeof(struct httpd_priv)); + if (!priv) + return 0; + + memset(priv, 0, sizeof(struct httpd_priv)); + priv->tcp = tcp; + + tcp->priv = priv; + tcp->on_closed = tcp_stream_on_closed; + tcp->on_rcv_nxt_update = tcp_stream_on_rcv_nxt_update; + tcp->rx = tcp_stream_rx; + tcp->on_snd_una_update = tcp_stream_on_snd_una_update; + tcp->tx = tcp_stream_tx; + return 1; +} + +void httpd_setup(struct httpd_config *config) +{ + cfg = config; +} + +void httpd_stop(void) +{ + stop_server = 1; +} + +void httpd_start(void) +{ + if (!cfg) { + net_set_state(NETLOOP_FAIL); + return; + } + stop_server = 0; + memset(net_server_ethaddr, 0, 6); + tcp_stream_set_on_create_handler(tcp_stream_on_create); + printf("HTTPD listening on port %d...\n", HTTP_PORT); +} diff --git a/net/net.c b/net/net.c index d81604a57ce..0b6cf4ef45c 100644 --- a/net/net.c +++ b/net/net.c @@ -109,6 +109,7 @@ #include #include #include +#include #include "arp.h" #include "bootp.h" #include "cdp.h" @@ -573,6 +574,11 @@ restart: netcat_save_start(); break; #endif +#if defined(CONFIG_HTTPD_COMMON) + case HTTPD: + httpd_start(); + break; +#endif #if defined(CONFIG_CMD_CDP) case CDP: cdp_start(); From patchwork Sat Aug 24 09:27:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Kshevetskiy X-Patchwork-Id: 1976367 X-Patchwork-Delegate: pbrobinson@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.a=rsa-sha256 header.s=selector2 header.b=uOwipLEj; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WrWq44P8Qz1yXd for ; Sat, 24 Aug 2024 19:29:20 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 8D0A0888D5; Sat, 24 Aug 2024 11:27:46 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.b="uOwipLEj"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 2A3CB888C1; Sat, 24 Aug 2024 11:27:44 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.8 required=5.0 tests=BAYES_00, CONTENT_AFTER_HTML, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, SPF_HELO_PASS,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 Received: from EUR05-DB8-obe.outbound.protection.outlook.com (mail-db8eur05on20702.outbound.protection.outlook.com [IPv6:2a01:111:f400:7e1a::702]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 4B1D688C97 for ; Sat, 24 Aug 2024 11:27:41 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mikhail.kshevetskiy@genexis.eu ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=Hh7+MYLBX+PfV1dNwt2O4aAiuSOUjvI6LrmQXDObZiYlJdB18JngcfTtwvcs7YEAixdNE4DrC/DQcXeV17/bsW+hNwo9Xjjhqc8kF4bYfBv6BRL+CPmvzvxbFMJ8QYZPvmzxuVjAzKdGxMLUOeyo47hu6WvAGM44VfJ7xGuxZiV2Em2ABQoO0F1m0T3K0/8IAEw8ujYImp9cNyTxy1+ihwcJzKDzQcD5UeHx+FnoKDzkCdMcDoBkfVzox4JGddV+oJbq1uw6TRDWsx5zFnfWHLeIr9wBAo53cTvHYN/OpjKu5GGszbBM6qdlX+Sc/QRe577jcjlcLVxImnE2FeeKCA== 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=YoFt4UFdyzHMIDNWxqwgCs1uTETlcZJ+xknUX5ebXiA=; b=LiZLb+KfwoHULspEczm1Qjmxikce/rwNTrdJEF+RS+VSriYfgYW8I6hRvf+acw/7rawApxRLBEKA2lTTjxyoI1wIBGhOnjNObfLcT08h0OT3/SHEYDj1+r1sXIxE0VmMoeTAzaxdaDpJ86QGsYQklloaFnRPI1FJitrRcxu3vzuOhvng0jIxZZyG2qWOG7ooGk4bgJdOZAPJ4/trk0Jnps78jAr6Rj6ukCMikc9IV6szMoVvhzg2SMZcA5DKgpGrTNq/8r1nR9xH2yiEsiokbOSn7824kW1pG00jS4NCGsBep+d9q10xs7q6+72slqW1ANn37XtxsDn92BAhQB0s1w== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=genexis.eu; dmarc=pass action=none header.from=iopsys.eu; dkim=pass header.d=iopsys.eu; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iopsys.eu; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=YoFt4UFdyzHMIDNWxqwgCs1uTETlcZJ+xknUX5ebXiA=; b=uOwipLEjSS7p4PLXfQA55vQOW1zR5ooWCPP7mRUhjyHPppssIRYLbYsOL5DOaGs7leTJoyyXH5wyiQ2WuLhPV69wRBGvg/Tspn8SXijQK7yd1m4OHJzrVEzCj0eb8T+VSfDVPoQ12HXLPy9WkhICB/+U7HD5vvWzssNtkk+3sDDriLQMjAykgM2aZD283nSeuNb9XwHD3mpLnlmBlMaDkkw5Ew3lRZx+/wVJF0J+2AjWO/QQhhsXDJUqbHIGVHlMZML0A4DEET19oMjR3mqKJBxjf0GwYH/JY8oy/e0pTBt3bpnDFIVNpWbV6MXEISQb4rEeppyKC5sDS5qu72LQhA== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=iopsys.eu; Received: from GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) by DB9PR08MB7445.eurprd08.prod.outlook.com (2603:10a6:10:36f::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7897.13; Sat, 24 Aug 2024 09:27:39 +0000 Received: from GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0]) by GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0%2]) with mapi id 15.20.7918.011; Sat, 24 Aug 2024 09:27:39 +0000 From: Mikhail Kshevetskiy To: Tom Rini , Joe Hershberger , Ramon Fried , Mattijs Korpershoek , Simon Glass , Heinrich Schuchardt , AKASHI Takahiro , Michal Simek , Francis Laniel , Anand Moon , Mikhail Kshevetskiy , Marek Vasut , Ilias Apalodimas , Masahisa Kojima , Sean Anderson , Baruch Siach , Yasuharu Shibata , u-boot@lists.denx.de Subject: [PATCH v5 11/11] net/httpd-upload: an example web-server implementation for file uploading Date: Sat, 24 Aug 2024 12:27:16 +0300 Message-ID: <20240824092716.1042696-12-mikhail.kshevetskiy@iopsys.eu> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240824092716.1042696-1-mikhail.kshevetskiy@iopsys.eu> References: <20240824092716.1042696-1-mikhail.kshevetskiy@iopsys.eu> X-ClientProxiedBy: GV3P280CA0011.SWEP280.PROD.OUTLOOK.COM (2603:10a6:150:b::7) To GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: GV2PR08MB8121:EE_|DB9PR08MB7445:EE_ X-MS-Office365-Filtering-Correlation-Id: 58e413c2-570f-47f3-f978-08dcc41eff9d X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|1800799024|366016|376014|52116014|7416014|921020|38350700014; X-Microsoft-Antispam-Message-Info: ahw7kD18J8VB7HSZIzSw77EmLqMPzPkA/NTuHLz+2pTdEPSEOhSPSNEk04UtegV+lF+LCi12l3btO7bTW8lor5mNMgh8tQG4+4mDtIIaSRQdtbwyX8yjfSInHGRO+Ql82XrTuybSd7bsF09VZYlOQ13Vonrjy1WMVcsKnqTZJe0/YDoq18OrPq0yTOMuDaklRjxsAfP/qBkgUjvQugBXOFIPLbIOXlR1WVMprCK+Btfmc4Y/gy/WGHFborjrQ1WwouWed7cEqUjZQEOlzJaPXGzrgFmOPthsEkwLWZVO9zJmppeAHzCO1BKlCcmT1ZmAZlK7AIuJ9pLGd5VK0S6hVXxBputKFePbMr6C9JuAdDZvhXXV7jc/QiEqzT2OxfTChrXR4JlTDqy8NoKPgWsmwMKZqpmR3s9EBjNQ2DtYYwY7/YV8Tza+gVOs8Q8GEfhARR/Slx9PBqzIA9y1WMeLzKstzbtI4DAq3FiEj4mp8uN7pjVz9X/5gdfxl0ki4TG6nGhwVXBUawQxwxA6beqfVx7gNLKaATPCIE+9x5pc9pvrbmQIi2fsSKubU3/3Rt6Xqn+7op4PCHrlOWD1WDF768UHy5GeNQNBz81LkjjdBuvs9x7aPswNT7VLhS65UuUl14SQH589kp/yagncdVM8UQ+c4Enat3MqEoxc5iXFw9WES+3PnsJPcdge4POEaAJ51MbVEr1q9txwt+8tIq5ib9QxGxJjVdfR9U1ANh5mo+7F8JabRv+XRq0/D6vopQSWqQfstDEjDsAYx2wxPDsHYJnvZdVN9fUN+l6+bxd854UTtvhojY6efWnpUcGkkljxmZyzFqmJ+Z2aSa32YiH4Us1aAPEqPFXcDlQd1frZfOzqW63hTSrAdWNJr+VvKozeEUoFhI5A35Wz8DA70qASDoMMo3d8vgudTbi9yi2sNCsFNgLvWgsTrYjIsk1aFvBqU7e6VvPVtQcW97bN+Df9NA3FTLfsqo88XL0OylhkL/XikqEZzJAs3+ZQJT/+BCazZwL1WQoC6hLR9Los70B+Wjjvil5InvTA6SKbZfigsdaQNc49NDxG3yk7IBw+jum1yJ6qO/tJjuamu+cIRqN+84UmVMtGuQpU+FTVMpFL5ErUg3vSWfLVQu97+YEE5xwCVZH1H6dljk1l/NDO885fzw57uGlIgZZA+L/RjWaNppHyUTeV7rQQvZKESRyAcnU0rJa61Q9SXGy3FCh4yo9bS+gpVe+WUgqbVRSdaCTkT1auRuxDpbo2UcxJn0vcu+EHQH9dNneb7oDE9d/rU5+odiZ0rZgfmphivctwOIYiLpIBD/PG2rLJqzY4a6vvYsqvLkOKc385NpZ6Ey80Bu4AoVnTHie32ulCY91OuymIIhGbpLug5mVgR8yJcgLeny7q6a/5RcrWqld6JXJd6FrIP/l2U+yVxPPLr7ADm4m9sRc= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:GV2PR08MB8121.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(1800799024)(366016)(376014)(52116014)(7416014)(921020)(38350700014); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: LRetwjxj4A+vV57WhD7ph1TTlc+oeobl6hhOJYQoflxVqNmVZMoBoQsNVuUYJmmuru54zaFfHkiGstJwYLDT5V/BsW2D0lHacwnrBw6ghlsvLwFP6Jh7nSsEIcqyQNkwdTtI8yPIEsPKM7Bw3RuXDP6gjk+QiEWKqF5oBBXfjZATD6rdiWb4wMjsgmoRjFK2TDznm1RKH70cKWE8BoqqJGs+4l17/BFxUjos5htCrmm6Gk421whNbDQrDrwapUvdPkgvfmBpMK2XLCmjfIozG3A414d0w7iMWZmGeTiBqV+X+xMi0GrWM48BmqYzFAKF+baxhFdatUBnsqtbYrAaN4CSb9PHpVy+5v/PaUOil/doQycqA+jw3F0eV65m7+oSB5OScN3qqHndfaN6C64Q9yJHWjXWLA8M6EdONO4Uph/5CXjJ4A4K2jqslBDfbqiSx3/5MxH2IvFMrK/RmKz7BoNKvFm+0Vjue3UCTCPPHcG5C3PbLbzc01uBIgXMvwATGNPQJha3LblyyfIUigmj39V3nCY9wJcUsOukNvvULdnEte3wQgA/jBvjfpkyqI2PDvFcEEF5h6cat/BgPD8vl+C2lp8u9gP7QJDWXkJllpLs7dCpiiOlVWcyrJ5Q4PvCGHogGlwYpFUNW/YVdewYS5Ugw2/KEsciYa8VfXrTVkZmYJGhUhCbNRnnnuW5inL0n4R2sKM7ipPXWbDZ/59IcbT36JO0jChnCRz0NCWc9pHKtRUkv4+0GR8Vq+X11kZuY6SyBZ3pOn01bQd/evbqcRKQYc7eQREwztPyoVmbc7rwkLyEnvERr9753PyRWfHCLa6gJz8MZklaj4JVwGERTXZlrVy6fbJRnNRQZLLdYAEuz9GDBEkiiLwp57/1FwNbmr8EWctARzTadV58sySsiMhklIUzbe1RliMXfmJUJ37unfSqjkr2eLHsW+pxTNgYyZkXfM0oU8Jly2agpDxe9j04u0J0e3pg5lqxHa6vc/dBf78/7q4hZi4mYsgXLp8Qi/jiQ2RHmQD/LhR6IT4yZA+eQZ6Iy6RncAJ24+Jg/yXwHLt4+bxVBSN2YiDijydsDs6z/j6Q/bGifkAlI/cmureD9afFplfGnKiw5KlO6jF+yI3Gv5Ms7CbWMiuci3Bl/HiQS52MJdX2H3H9efux0w8yEd/cWy/Q85qotW7oKRiJwKl45ASspnXBni+RiSwLlrgV16kA+Cf2F9fW3wpHYX0tX+PWg/TilVa9kkxHL5YgfcYT/2f4opTqX5Q9Wc2Jz8QNZfrinCXBsaQrljOYMNTMJHrXpHAgBdh+9aqvWad2pDp7wLerfsexLZHfGS1uZhQol796/3U8cA9TlSfUYQ/WaPSByWCnghdVVlzjxEIPZWWa9lEAMxMxPEZZKRPYmkCqur1qX3m9mP8w86Ra9irDurMqH0lAtYZcml8CuBdWn+v5U/sTSmPHcblZIeJi4jbyWJkECopeuLfVMayVfOfiTiMHdx0eOyy3RHfcK0ZnAubGfB25wwJj/lGcu86qLdlKENbSgpAxGjXIYgCNnvoQR714OJws2VfowsgfGQEpjzq5YqJrJTdmF0C3aWryjlhkCq1ArBlqW/5EskaXyVHyDEh25EN+lk3QKAJQftw= X-OriginatorOrg: iopsys.eu X-MS-Exchange-CrossTenant-Network-Message-Id: 58e413c2-570f-47f3-f978-08dcc41eff9d X-MS-Exchange-CrossTenant-AuthSource: GV2PR08MB8121.eurprd08.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Aug 2024 09:27:39.7670 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 8d891be1-7bce-4216-9a99-bee9de02ba58 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: RWzXfVGSVRZbL4q3MgetRnIXG0gxjHv3n2X73nLuGXfg5+QFj66BjSNRrjGPPkfrBN8eNdQVk/ixiw+Pk71qiRAywFHbYGmZkwXawv7r41Q= X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB9PR08MB7445 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean This is an example web-server implementation. It can be used for files uploading to u-boot using a web-browser. It acts much like tftpget, but no special servers needs to be installed by the user. This code can be used as a base for other implementations like firmware upgrade web-server used by some vendors. Usage: u-boot: start the we-server using the "httpd_upload" command PC: open the "http://your_uboot_ip" link in the browser Signed-off-by: Mikhail Kshevetskiy Reviewed-by: Simon Glass --- cmd/Kconfig | 14 ++++ cmd/net.c | 20 ++++++ include/net/httpd-upload.h | 12 ++++ net/Makefile | 19 +++++ net/httpd-upload.c | 123 ++++++++++++++++++++++++++++++++ net/httpd_upload/error_400.html | 9 +++ net/httpd_upload/error_404.html | 10 +++ net/httpd_upload/index.html | 14 ++++ net/httpd_upload/upload_ok.html | 7 ++ 9 files changed, 228 insertions(+) create mode 100644 include/net/httpd-upload.h create mode 100644 net/httpd-upload.c create mode 100644 net/httpd_upload/error_400.html create mode 100644 net/httpd_upload/error_404.html create mode 100644 net/httpd_upload/index.html create mode 100644 net/httpd_upload/upload_ok.html diff --git a/cmd/Kconfig b/cmd/Kconfig index abcd003f7f1..55b9d04f2fa 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -2014,6 +2014,20 @@ config CMD_NETCAT netcat is a simple command to load/store kernel, or other files, using netcat like manner over TCP. +config CMD_HTTPD_UPLOAD + bool "an example HTTP server for file uploading" + depends on HTTPD_COMMON + help + HTTP/1.1 compatible server for file uploading. + +config CMD_HTTPD_UPLOAD_MAX_SIZE + int "Maximum uploading size" + depends on CMD_HTTPD_UPLOAD + default 209715200 + help + This sets maximum size of uploaded file. Real transfer will be + slightly more than this limit. + config CMD_MII bool "mii" imply CMD_MDIO diff --git a/cmd/net.c b/cmd/net.c index 364139ec5b9..e5fddc8c7c5 100644 --- a/cmd/net.c +++ b/cmd/net.c @@ -21,6 +21,9 @@ #include #include #include +#if defined(CONFIG_CMD_HTTPD_UPLOAD) +#include +#endif static int netboot_common(enum proto_t, struct cmd_tbl *, int, char * const []); @@ -228,6 +231,23 @@ U_BOOT_CMD( ); #endif +#if defined(CONFIG_CMD_HTTPD_UPLOAD) +static int do_httpd_upload(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + if (argc < 2) + return 1; + + httpd_upload_prepare(); + return netboot_common(HTTPD, cmdtp, argc, argv); +} + +U_BOOT_CMD( + httpd_upload, 2, 1, do_httpd_upload, + "starts httpd server for file uploading", + "[loadAddress]\n" +); +#endif + static void netboot_update_env(void) { char tmp[46]; diff --git a/include/net/httpd-upload.h b/include/net/httpd-upload.h new file mode 100644 index 00000000000..a80df214668 --- /dev/null +++ b/include/net/httpd-upload.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: BSD-2-Clause + * + * httpd-upload include file + * Copyright (C) 2024 IOPSYS Software Solutions AB + * Author: Mikhail Kshevetskiy + */ +#ifndef __NET_HTTPD_UPLOAD_TCP_H__ +#define __NET_HTTPD_UPLOAD_TCP_H__ + +void httpd_upload_prepare(void); + +#endif /* __NET_HTTPD_UPLOAD_TCP_H__ */ diff --git a/net/Makefile b/net/Makefile index c1f491fad02..e7cbbc2248e 100644 --- a/net/Makefile +++ b/net/Makefile @@ -35,8 +35,27 @@ obj-$(CONFIG_PROT_TCP) += tcp.o obj-$(CONFIG_CMD_WGET) += wget.o obj-$(CONFIG_CMD_NETCAT) += netcat.o obj-$(CONFIG_HTTPD_COMMON) += httpd.o +obj-$(CONFIG_CMD_HTTPD_UPLOAD) += httpd-upload.o # Disable this warning as it is triggered by: # sprintf(buf, index ? "foo%d" : "foo", index) # and this is intentional usage. CFLAGS_eth_common.o += -Wno-format-extra-args + +STATIC_SUBST := 's/^\(unsigned char \)/static \1/' +SIZE_REMOVE_SUBST := 's/^unsigned int .*//' + +httpd_upload_generated: + rm -rf $(src)/httpd_upload_generated + mkdir -p $(src)/httpd_upload_generated + cd $(src)/httpd_upload && find . -type f | while read fname; do \ + name="$${fname##*/}" && \ + name="$${name%%.*}" && \ + set -o pipefail && xxd -i "$${fname##./}" | \ + sed $(STATIC_SUBST) | \ + sed $(SIZE_REMOVE_SUBST) > ../httpd_upload_generated/$${name}.h; \ + done + +.PHONY: httpd_upload_generated + +net/httpd-upload.o: httpd_upload_generated diff --git a/net/httpd-upload.c b/net/httpd-upload.c new file mode 100644 index 00000000000..1e1e0b1cf75 --- /dev/null +++ b/net/httpd-upload.c @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * httpd-upload support driver + * Copyright (C) 2024 IOPSYS Software Solutions AB + * Author: Mikhail Kshevetskiy + */ + +#include +#include +#include +#include + +#define MAX_FILE_SIZE CONFIG_CMD_HTTPD_UPLOAD_MAX_SIZE + +static enum net_loop_state httpd_on_stop(void); + +static enum httpd_req_check httpd_pre_post(void *req_id, const char *url, + struct httpd_post_data *post); +static struct http_reply *httpd_get(void *req_id, const char *url); +static struct http_reply *httpd_post(void *req_id, const char *url, + struct httpd_post_data *post); +static void httpd_on_req_end(void *req_id); + +#include "httpd_upload_generated/error_400.h" +#include "httpd_upload_generated/error_404.h" +#include "httpd_upload_generated/index.h" +#include "httpd_upload_generated/upload_ok.h" + +static struct http_reply error_400 = { + .code = 400, + .code_msg = "Bad Request", + .data_type = "text/html; charset=utf-8", + .data = error_400_html, + .len = sizeof(error_400_html) +}; + +static struct http_reply error_404 = { + .code = 404, + .code_msg = "Not Found", + .data_type = "text/html; charset=utf-8", + .data = error_404_html, + .len = sizeof(error_404_html) +}; + +static struct http_reply index = { + .code = 200, + .code_msg = "OK", + .data_type = "text/html; charset=utf-8", + .data = index_html, + .len = sizeof(index_html) +}; + +static struct http_reply upload_ok = { + .code = 200, + .code_msg = "OK", + .data_type = "text/html; charset=utf-8", + .data = upload_ok_html, + .len = sizeof(upload_ok_html) +}; + +static struct httpd_config cfg = { + .on_stop = httpd_on_stop, + .on_req_end = httpd_on_req_end, + .get = httpd_get, + .post = httpd_post, + .pre_post = httpd_pre_post, + .error_400 = &error_400, + .error_404 = &error_404, +}; + +static enum net_loop_state httpd_loop_state; +static void *post_req_id; + +void httpd_upload_prepare(void) +{ + httpd_setup(&cfg); + httpd_loop_state = NETLOOP_FAIL; +} + +static enum httpd_req_check httpd_pre_post(void *req_id, const char *url, + struct httpd_post_data *post) +{ + if (post->size > MAX_FILE_SIZE) { + printf("HTTPD: reset connection, upload file is too large\n"); + return HTTPD_CLNT_RST; + } + + post_req_id = req_id; + return HTTPD_REQ_OK; +} + +static struct http_reply *httpd_post(void *req_id, const char *url, + struct httpd_post_data *post) +{ + if (strcmp(url, "/file_upload")) + return &error_404; + + httpd_loop_state = NETLOOP_SUCCESS; + printf("HTTPD: upload OK\n"); + return &upload_ok; +} + +static struct http_reply *httpd_get(void *req_id, const char *url) +{ + if (!strcmp(url, "/")) + return &index; + if (!strcmp(url, "/index.html")) + return &index; + return &error_404; +} + +static void httpd_on_req_end(void *req_id) +{ + if (req_id == post_req_id) { + post_req_id = NULL; + httpd_stop(); + } +} + +static enum net_loop_state httpd_on_stop(void) +{ + return httpd_loop_state; +} diff --git a/net/httpd_upload/error_400.html b/net/httpd_upload/error_400.html new file mode 100644 index 00000000000..de654364edf --- /dev/null +++ b/net/httpd_upload/error_400.html @@ -0,0 +1,9 @@ + + 400 + +

400 - Bad Request

+

+ Sorry, the request you are trying to do is wrong. +

+ + diff --git a/net/httpd_upload/error_404.html b/net/httpd_upload/error_404.html new file mode 100644 index 00000000000..9dac22d497d --- /dev/null +++ b/net/httpd_upload/error_404.html @@ -0,0 +1,10 @@ + + 404 + +

404 - Page not found

+

+ Sorry, the page you are requesting was not found on this + server. +

+ + diff --git a/net/httpd_upload/index.html b/net/httpd_upload/index.html new file mode 100644 index 00000000000..e7d5ac943b6 --- /dev/null +++ b/net/httpd_upload/index.html @@ -0,0 +1,14 @@ + + Upload File + +

Upload File.

+

This will write the uploaded file to the memory arear pointed by ${loadaddr}. +

+ File to upload: +
+

   +

It takes no more than a second after the file has been uploaded until status OK is shown. +

+

+ + diff --git a/net/httpd_upload/upload_ok.html b/net/httpd_upload/upload_ok.html new file mode 100644 index 00000000000..8d2e561982f --- /dev/null +++ b/net/httpd_upload/upload_ok.html @@ -0,0 +1,7 @@ + + OK + +

Upload OK

+

The file was uploaded.

+ +