From patchwork Wed Oct 9 14:49:59 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Forissier X-Patchwork-Id: 833962 Delivered-To: patch@linaro.org Received: by 2002:adf:a1de:0:b0:37d:45d0:187 with SMTP id v30csp150531wrv; Wed, 9 Oct 2024 07:52:20 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCVS5GQdU2s5SvD/Vl7TcVa6wlUmzS0UdqoBAocJ3CvvMduPS/ngiSO1nuEp7sn3d+RUdAmqRQ==@linaro.org X-Google-Smtp-Source: AGHT+IETY63EKubzyq8Q/L3uLK6UEKFov23Zsz+YGzVba9IQEUc/VJdh2HgfggC8SCVUrUg8cgVZ X-Received: by 2002:a05:600c:3b88:b0:42e:8d0d:bca5 with SMTP id 5b1f17b1804b1-430ccf1b30bmr19902955e9.2.1728485540559; Wed, 09 Oct 2024 07:52:20 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1728485540; cv=none; d=google.com; s=arc-20240605; b=CbMq79bnory+Yf722wu0KeB+iKhUzsZxJBHDCg7ZzvXyG6aF97qUaGvSXsGagvrRDi B9r0VK+gbnl+UN7jz1gftLIZQlMZsUdd60VGPZG9Rt4XO190DL0yJB+73Lczp44k8cZ4 x+oPQ6Oc02Q0lm4udL2y/JqyMNRmSrWDvVrEVGdOSxZR2+V1c9yPKZ+WuG42xV+ACcAP kwzu3AZbWLCG63djGc2DaESggqkqM3vnAyvN/0lb9QVP+dYbA4xDIIcMytxNfPEiXLYi VGMtpFEGko6FOvpfl/E77l2vcaBwDmZjhNz6/x6Uat3dlXMKkc5rLbXIdLfsyKwk7YU8 onqQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=3pyPnWroAAxeaL2wHrl7qplR/MmloZWJr7yEfC4wNrE=; fh=ThdVVZAeTRhYRIsitiRafY870JZ08RRoQKK9619Vak0=; b=e0eI+WPxHGySUPsuEJ+tzxvEPrTGcA+Fy5WaOV00AdOydGMb9y9EDeTnFzmvntpODe IwhQwbe+FyTFSUmyEoNku5PULkZiiLAKZj1VIBlAnAgO1rkhzFWtEhS5H9AETd0a4qF8 tpk6P8IJQIOXNQ8hGfJ77aHKF3r9aSo9plqgLa4aUYOWPsZlN5+ITUDRugVLBFKEMfD1 pxkCNH9tczo0+hnPUJEweaXyDOQ8fYlMOALRRvRP9dGZ8ZYuqCdrEtogYFhyFWp3GVoZ j1iy3aLrGeb5mBgreJ9wFX/cLCC3ZEXIxe9A/0DYD489UeKSa3gpfa6teDsm3ij8LqeL NlxA==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="rl/KZx63"; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org; dara=neutral header.i=@linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [2a01:238:438b:c500:173d:9f52:ddab:ee01]) by mx.google.com with ESMTPS id 5b1f17b1804b1-430d59b280dsi8733245e9.177.2024.10.09.07.52.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Oct 2024 07:52:20 -0700 (PDT) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="rl/KZx63"; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org; dara=neutral header.i=@linaro.org Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id C211D891A9; Wed, 9 Oct 2024 16:50:43 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org 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=linaro.org header.i=@linaro.org header.b="rl/KZx63"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 777258919B; Wed, 9 Oct 2024 16:50: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=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_BLOCKED, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wm1-x32c.google.com (mail-wm1-x32c.google.com [IPv6:2a00:1450:4864:20::32c]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 00BF188CF1 for ; Wed, 9 Oct 2024 16:50:39 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=jerome.forissier@linaro.org Received: by mail-wm1-x32c.google.com with SMTP id 5b1f17b1804b1-42cc43454d5so55806425e9.3 for ; Wed, 09 Oct 2024 07:50:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1728485439; x=1729090239; darn=lists.denx.de; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=3pyPnWroAAxeaL2wHrl7qplR/MmloZWJr7yEfC4wNrE=; b=rl/KZx63aAfLzX1VRY26UWJ/lG/Km+WaGBwm6+jWGg1zAWraqqQX3VQCxAMAIs1Spi L8Sk0OGa53KSzCg92yZ1ta9QASJNoguF9AdrLxmcUFsr6g1yEQUi1VMEGs3b1gSnAgmv BjayO6+InYwGYBCdwNcDgdE0kujwk9iNCdmy1LSuhjhPTIEf8Xg3GFoVegXz0dkU2dmx Pz6ZAktaDw9DlNDt9Kb3gFemFsiSmsWGve84sfoUIEjCE5AH4qBfSg2/UlKLkk44vJ22 6A4yBEkeVLCNSGeWol/FZi8V9RKhZsx5ByrB71GJA7Nhl3JYYgO3TwVmJ4ZYNfcwaJbI 4KAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728485439; x=1729090239; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=3pyPnWroAAxeaL2wHrl7qplR/MmloZWJr7yEfC4wNrE=; b=h9GRbkvZLT6o5trDtRz0mjDCsig2uqpIltajxmiekJkWwB2gNwV9HX3Xjx/ZFzf9AD jx5FJSPe471g1XgJKql+Srfvi4GUx6VTKuVQga+ki6M85p3o0szlZKbyQJQIe4JZQVA5 vIlyq9Xta90r5s+rC7A06AKiCUtby8oHMSPI/ZtJq8L+zSpTrwyDQpoD5ztn5aROCHQ1 mtDpFXX1w9hczbcMQACa95XI/ZsZI7bfacm55SDtp7rSsTlAd4OfsoeFW9beEg8QBqup HSHUDQQVD8vmNllkYAxVFQbTm8Yh+ExUibYfD/QPVOskmP+6DC11MkWrmcg4R0tw4EU+ O4ig== X-Gm-Message-State: AOJu0Yxz227rU3Bhww+WN4VkQ94Nh36G4jh68Zy18CmMiuzQ30zsVXNq OGTRX6Fcqt176g3JAbiKwVK+VQUq2sNk3Sb7r8oR7qMIMrlfKNJ1kX6kwk94M/dtq/QAekfSvBh f8F8jEnPT X-Received: by 2002:a05:600c:45d1:b0:426:6308:e2f0 with SMTP id 5b1f17b1804b1-430d729f2cdmr20739315e9.26.1728485439157; Wed, 09 Oct 2024 07:50:39 -0700 (PDT) Received: from builder.. ([2a01:e0a:3cb:7bb0:9b46:2ad8:5153:1163]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-37d1691b5ddsm10700957f8f.47.2024.10.09.07.50.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Oct 2024 07:50:38 -0700 (PDT) From: Jerome Forissier To: u-boot@lists.denx.de Cc: Ilias Apalodimas , Javier Tia , Raymond Mao , Maxim Uvarov , Tim Harvey , Anton Antonov , Jerome Forissier , Tom Rini Subject: [PATCH v12 18/21] net: lwip: tftp: add support of blksize option to client Date: Wed, 9 Oct 2024 16:49:59 +0200 Message-Id: <6de92bad17c86e300e3ae4d1b8b67569b350410c.1728482473.git.jerome.forissier@linaro.org> X-Mailer: git-send-email 2.40.1 In-Reply-To: References: MIME-Version: 1.0 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 The TFTP protocol uses a default block size of 512 bytes. This value is sub-optimal for ethernet devices, which have a MTU (Maximum Transmission Unit) of 1500 bytes. When taking into acount the overhead of the IP and UDP layers, this leaves 1468 bytes for the TFTP payload. This patch introduces a new function: tftp_client_set_blksize() which may be used to change the block size from the default. It has to be called after tftp_client_init() and before tftp_get(). If the server does not support the option, the client will still accept to receive 512-byte blocks. Submitted upstream: https://savannah.nongnu.org/patch/index.php?10462 Signed-off-by: Jerome Forissier Acked-by: Ilias Apalodimas --- lib/lwip/lwip/src/apps/tftp/tftp.c | 94 +++++++++++++++++-- .../lwip/src/include/lwip/apps/tftp_client.h | 1 + 2 files changed, 89 insertions(+), 6 deletions(-) diff --git a/lib/lwip/lwip/src/apps/tftp/tftp.c b/lib/lwip/lwip/src/apps/tftp/tftp.c index 74fc1fbe586..8e0c071772a 100644 --- a/lib/lwip/lwip/src/apps/tftp/tftp.c +++ b/lib/lwip/lwip/src/apps/tftp/tftp.c @@ -57,7 +57,7 @@ #include "lwip/timeouts.h" #include "lwip/debug.h" -#define TFTP_MAX_PAYLOAD_SIZE 512 +#define TFTP_DEFAULT_BLOCK_SIZE 512 #define TFTP_HEADER_LENGTH 4 #define TFTP_RRQ 1 @@ -65,6 +65,7 @@ #define TFTP_DATA 3 #define TFTP_ACK 4 #define TFTP_ERROR 5 +#define TFTP_OACK 6 enum tftp_error { TFTP_ERROR_FILE_NOT_FOUND = 1, @@ -88,9 +89,11 @@ struct tftp_state { int timer; int last_pkt; u16_t blknum; + u16_t blksize; u8_t retries; u8_t mode_write; u8_t tftp_mode; + bool wait_oack; }; static struct tftp_state tftp_state; @@ -137,10 +140,24 @@ send_request(const ip_addr_t *addr, u16_t port, u16_t opcode, const char* fname, { size_t fname_length = strlen(fname)+1; size_t mode_length = strlen(mode)+1; - struct pbuf* p = init_packet(opcode, 0, fname_length + mode_length - 2); + size_t blksize_length = 0; + struct pbuf* p; char* payload; err_t ret; + if (tftp_state.blksize) { + blksize_length = 14; /* maximum (blksize is a u16_t): 'blksize\0XXXXX\0' */ + if (tftp_state.blksize < 10000) + blksize_length--; + if (tftp_state.blksize < 1000) + blksize_length--; + if (tftp_state.blksize < 100) + blksize_length--; + if (tftp_state.blksize < 10) + blksize_length--; + } + + p = init_packet(opcode, 0, fname_length + mode_length + blksize_length - 2); if (p == NULL) { return ERR_MEM; } @@ -148,7 +165,10 @@ send_request(const ip_addr_t *addr, u16_t port, u16_t opcode, const char* fname, payload = (char*) p->payload; MEMCPY(payload+2, fname, fname_length); MEMCPY(payload+2+fname_length, mode, mode_length); + if (tftp_state.blksize) + sprintf(payload+2+fname_length+mode_length, "blksize%c%d%c", 0, tftp_state.blksize, 0); + tftp_state.wait_oack = true; ret = udp_sendto(tftp_state.upcb, p, addr, port); pbuf_free(p); return ret; @@ -221,14 +241,14 @@ send_data(const ip_addr_t *addr, u16_t port) pbuf_free(tftp_state.last_data); } - tftp_state.last_data = init_packet(TFTP_DATA, tftp_state.blknum, TFTP_MAX_PAYLOAD_SIZE); + tftp_state.last_data = init_packet(TFTP_DATA, tftp_state.blknum, TFTP_DEFAULT_BLOCK_SIZE); if (tftp_state.last_data == NULL) { return; } payload = (u16_t *) tftp_state.last_data->payload; - ret = tftp_state.ctx->read(tftp_state.handle, &payload[2], TFTP_MAX_PAYLOAD_SIZE); + ret = tftp_state.ctx->read(tftp_state.handle, &payload[2], TFTP_DEFAULT_BLOCK_SIZE); if (ret < 0) { send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Error occurred while reading the file."); close_handle(); @@ -239,6 +259,28 @@ send_data(const ip_addr_t *addr, u16_t port) resend_data(addr, port); } +static u16_t payload_size(void) +{ + if (tftp_state.blksize) + return tftp_state.blksize; + return TFTP_DEFAULT_BLOCK_SIZE; +} + +static const char * +find_option(struct pbuf *p, const char *option) +{ + int i; + u16_t optlen = strlen(option); + const char *b = p->payload; + + for (i = 0; i + optlen + 1 < p->len; i++) { + if (lwip_strnstr(b + i, option, optlen)) + return b + i + optlen + 2; + } + + return NULL; +} + static void tftp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) { @@ -338,6 +380,15 @@ tftp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr } blknum = lwip_ntohs(sbuf[1]); + if (tftp_state.blksize && tftp_state.wait_oack) { + /* + * Data received while we are expecting an OACK for our blksize option. + * This means the server doesn't support it, let's switch back to the + * default block size. + */ + tftp_state.blksize = 0; + tftp_state.wait_oack = false; + } if (blknum == tftp_state.blknum) { pbuf_remove_header(p, TFTP_HEADER_LENGTH); @@ -349,7 +400,7 @@ tftp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr send_ack(addr, port, blknum); } - if (p->tot_len < TFTP_MAX_PAYLOAD_SIZE) { + if (p->tot_len < payload_size()) { close_handle(); } else { tftp_state.blknum++; @@ -386,7 +437,7 @@ tftp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr lastpkt = 0; if (tftp_state.last_data != NULL) { - lastpkt = tftp_state.last_data->tot_len != (TFTP_MAX_PAYLOAD_SIZE + TFTP_HEADER_LENGTH); + lastpkt = tftp_state.last_data->tot_len != (TFTP_DEFAULT_BLOCK_SIZE + TFTP_HEADER_LENGTH); } if (!lastpkt) { @@ -405,6 +456,25 @@ tftp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr close_handle(); } break; + case PP_HTONS(TFTP_OACK): { + const char *optval = find_option(p, "blksize"); + u16_t srv_blksize = 0; + tftp_state.wait_oack = false; + if (optval) { + if (!tftp_state.blksize) { + /* We did not request this option */ + send_error(addr, port, TFTP_ERROR_ILLEGAL_OPERATION, "blksize unexpected"); + } + srv_blksize = atoi(optval); + if (srv_blksize <= 0 || srv_blksize > tftp_state.blksize) { + send_error(addr, port, TFTP_ERROR_ILLEGAL_OPERATION, "Invalid blksize"); + } + LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: accepting blksize=%d\n", srv_blksize)); + tftp_state.blksize = srv_blksize; + } + send_ack(addr, port, 0); + break; + } default: send_error(addr, port, TFTP_ERROR_ILLEGAL_OPERATION, "Unknown operation"); break; @@ -495,6 +565,18 @@ tftp_init_client(const struct tftp_context *ctx) return tftp_init_common(LWIP_TFTP_MODE_CLIENT, ctx); } +/** @ingroup tftp + * Set the block size to be used by the TFTP client. The server may choose to + * accept a lower value. + * @param blksize Block size in bytes + */ +void +tftp_client_set_blksize(u16_t blksize) +{ + if (blksize != TFTP_DEFAULT_BLOCK_SIZE) + tftp_state.blksize = blksize; +} + /** @ingroup tftp * Deinitialize ("turn off") TFTP client/server. */ diff --git a/lib/lwip/lwip/src/include/lwip/apps/tftp_client.h b/lib/lwip/lwip/src/include/lwip/apps/tftp_client.h index 24dbda6a8c9..e1e21d06b67 100644 --- a/lib/lwip/lwip/src/include/lwip/apps/tftp_client.h +++ b/lib/lwip/lwip/src/include/lwip/apps/tftp_client.h @@ -44,6 +44,7 @@ enum tftp_transfer_mode { }; err_t tftp_init_client(const struct tftp_context* ctx); +void tftp_client_set_blksize(u16_t blksize); err_t tftp_get(void* handle, const ip_addr_t *addr, u16_t port, const char* fname, enum tftp_transfer_mode mode); err_t tftp_put(void* handle, const ip_addr_t *addr, u16_t port, const char* fname, enum tftp_transfer_mode mode);