From patchwork Fri May 15 10:00:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ramon Fried X-Patchwork-Id: 1290987 X-Patchwork-Delegate: joe.hershberger@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: 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=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=OflUz0fP; dkim-atps=neutral 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 RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49NkSd1FDDz9sSF for ; Fri, 15 May 2020 20:01:05 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 3AF2481FB1; Fri, 15 May 2020 12:01:00 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com 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=gmail.com header.i=@gmail.com header.b="OflUz0fP"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 1292681FB1; Fri, 15 May 2020 12:00:58 +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.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wr1-x432.google.com (mail-wr1-x432.google.com [IPv6:2a00:1450:4864:20::432]) (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 D450481FB1 for ; Fri, 15 May 2020 12:00:48 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=rfried.dev@gmail.com Received: by mail-wr1-x432.google.com with SMTP id i15so2776733wrx.10 for ; Fri, 15 May 2020 03:00:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=bYi+JbTB4mOO42r2ot+fBhblvfQ1X630hoNro1XWtzY=; b=OflUz0fPiv62ZmD98Ux1veoLWc4ytD5ilV9r/qzfvBVZDBMlg2WEJCwiu4ZqEbo6G/ Ril9+4FikmUyt8rbwyoQsyN1ocWwBBAXLM0ofq9b3aP3QZKr6RCxjEduHzqJ+hddHByW /OkKJP2YermDQBbqiiKoxNgF7wLQWZZcVz0SxWvDL8RNpuaBLjbeDp/1OOStbfA5g4hv nLL0f/zrKS4CYDlCnQXV2Gw+zWJ9AlUDSfPh7oWnRk4agp5Bt6hHVC4WWKqRxqyygjVL zEX+/FxrbRkMApKruWKRsAKaRqB0hItAXUU4z8iaplN2WENnX0N7tWSl8CeUkO9OdyU9 mlQA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=bYi+JbTB4mOO42r2ot+fBhblvfQ1X630hoNro1XWtzY=; b=VYNURPF1CBPlgdHLgHicVUS4c9yJ3a00zkcp1MS0roHXPEWgkGMxURpnxuKrElN2iV 7cAvh7Xdoef3yhJrnqAcLNcc2KXdAteTaYermJ+IVZEYPnDsUs8hINAXksXgyg5vGCRh muJkkAPMe1x0sTLBLFJoyfmYCVejxov5RPjS7OTDaUGipmpRgcoYqqvni/2pfOJ6UJdT 7tDEmGNGNbqogFgSGFn8oN3CtXF/5rM9/9qL1CK+2YoZVKaQkwnDARj7B3F9ukzEJYuK Be7uDzZx3BovobI4JdSA4t7gwZSIfPnnJ6DWVaayGa4sITQ4D34Zy1M4Nydbo1NxxrXG HcFA== X-Gm-Message-State: AOAM532pvMo8kbTKQD1BIxs+EZe3qTxhD0yCrTXl4ENsac0egJUGy9uX XNytWctLFpBKDHVkal6V+Iw= X-Google-Smtp-Source: ABdhPJzDDJxCBXEpeh7M0689KxQKgM8b7fxB4hzpHNdwcN3+Q1IGuyi26FekpSloWQP//3Q12fmP1w== X-Received: by 2002:a5d:4651:: with SMTP id j17mr3215036wrs.50.1589536848139; Fri, 15 May 2020 03:00:48 -0700 (PDT) Received: from localhost.localdomain ([37.142.6.51]) by smtp.gmail.com with ESMTPSA id 37sm2923514wrk.61.2020.05.15.03.00.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 May 2020 03:00:47 -0700 (PDT) From: Ramon Fried To: joe.hershberger@ni.com, Marek Vasut , u-boot@lists.denx.de Cc: Ramon Fried Subject: [PATCH] net: tftp: Add client support for RFC 7440 Date: Fri, 15 May 2020 13:00:32 +0300 Message-Id: <20200515100032.13410-1-rfried.dev@gmail.com> X-Mailer: git-send-email 2.26.2 MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 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.102.2 at phobos.denx.de X-Virus-Status: Clean Add support for RFC 7440: "TFTP Windowsize Option". This optional feature allows the client and server to negotiate a window size of consecutive blocks to send as an alternative for replacing the single-block lockstep schema. windowsize can be defined statically during compilation by setting CONFIG_TFTP_WINDOWSIZE, or defined in runtime by setting an environment variable: "tftpwindowsize" If not defined, the windowsize is set to 1, meaning that it behaves as it was never defined. Choosing the appropriate windowsize depends on the specific network topology, underlying NIC. You should test various windowsize scenarios and see which best work for you. Setting a windowsize too big can actually decreases performance. Signed-off-by: Ramon Fried Reviewed-by: Marek Vasut --- README | 5 +++++ net/tftp.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 59 insertions(+), 5 deletions(-) diff --git a/README b/README index be9e6391d6..b85b44201f 100644 --- a/README +++ b/README @@ -3522,6 +3522,11 @@ List of environment variables (most likely not complete): downloads succeed with high packet loss rates, or with unreliable TFTP servers or client hardware. + tftpwindowsize - if this is set, the value is used for TFTP's + window size as described by RFC 7440. + This means that count of blocks we can receive before + sending ack to server. + vlan - When set to a value < 4095 the traffic over Ethernet is encapsulated/received over 802.1q VLAN tagged frames. diff --git a/net/tftp.c b/net/tftp.c index be24e63075..e3e72eba68 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -5,7 +5,6 @@ * Copyright 2011 Comelit Group SpA, * Luca Ceresoli */ - #include #include #include @@ -95,6 +94,10 @@ static int tftp_tsize; /* The number of hashes we printed */ static short tftp_tsize_num_hash; #endif +/* The window size neogiciated */ +static ushort tftp_windowsize; +/* Next block to send ack to */ +static ushort tftp_next_ack; #ifdef CONFIG_CMD_TFTPPUT /* 1 if writing, else 0 */ static int tftp_put_active; @@ -134,8 +137,19 @@ static char tftp_filename[MAX_LEN]; * (but those using CONFIG_IP_DEFRAG may want to set a larger block in cfg file) */ +/* When windowsize is defined to 1, + * tftp behaves the same way as it was + * never declared + */ +#ifdef CONFIG_TFTP_WINDOWSIZE +#define TFTP_WINDOWSIZE CONFIG_TFTP_WINDOWSIZE +#else +#define TFTP_WINDOWSIZE 1 +#endif + static unsigned short tftp_block_size = TFTP_BLOCK_SIZE; static unsigned short tftp_block_size_option = CONFIG_TFTP_BLOCKSIZE; +static unsigned short tftp_window_size_option = TFTP_WINDOWSIZE; static inline int store_block(int block, uchar *src, unsigned int len) { @@ -348,6 +362,13 @@ static void tftp_send(void) /* try for more effic. blk size */ pkt += sprintf((char *)pkt, "blksize%c%d%c", 0, tftp_block_size_option, 0); + + /* try for more effic. window size. + * Don't bother sending if it's 1 + */ + if (tftp_window_size_option > 1) + pkt += sprintf((char *)pkt, "windowsize%c%d%c", + 0, tftp_window_size_option, 0); len = pkt - xp; break; @@ -500,6 +521,15 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip, (char *)pkt + i + 6, tftp_tsize); } #endif + if (strcmp((char *)pkt + i, "windowsize") == 0) { + tftp_windowsize = + simple_strtoul((char *)pkt + i + 11, + NULL, 10); + debug("windowsize = %s, %d\n", + (char *)pkt + i + 11, tftp_windowsize); + } + + tftp_next_ack = tftp_windowsize; } #ifdef CONFIG_CMD_TFTPPUT if (tftp_put_active) { @@ -514,6 +544,18 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip, if (len < 2) return; len -= 2; + + if (ntohs(*(__be16 *)pkt) != (ushort)(tftp_cur_block + 1)) { + debug("Received unexpected block: %d, expected: %d\n", + ntohs(*(__be16 *)pkt), + (ushort)(tftp_cur_block + 1)); + + tftp_send(); + tftp_next_ack = (ushort)(tftp_cur_block + + tftp_windowsize); + break; + } + tftp_cur_block = ntohs(*(__be16 *)pkt); update_block_number(); @@ -557,7 +599,10 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip, * Acknowledge the block just received, which will prompt * the remote for the next one. */ - tftp_send(); + if (tftp_cur_block == tftp_next_ack) { + tftp_send(); + tftp_next_ack += tftp_windowsize; + } if (len < tftp_block_size) tftp_complete(); @@ -634,6 +679,10 @@ void tftp_start(enum proto_t protocol) if (ep != NULL) tftp_block_size_option = simple_strtol(ep, NULL, 10); + ep = env_get("tftpwindowsize"); + if (ep != NULL) + tftp_window_size_option = simple_strtol(ep, NULL, 10); + ep = env_get("tftptimeout"); if (ep != NULL) timeout_ms = simple_strtol(ep, NULL, 10); @@ -655,8 +704,8 @@ void tftp_start(enum proto_t protocol) } #endif - debug("TFTP blocksize = %i, timeout = %ld ms\n", - tftp_block_size_option, timeout_ms); + debug("TFTP blocksize = %i, TFTP windowsize = %d timeout = %ld ms\n", + tftp_block_size_option, tftp_window_size_option, timeout_ms); tftp_remote_ip = net_server_ip; if (!net_parse_bootfile(&tftp_remote_ip, tftp_filename, MAX_LEN)) { @@ -752,7 +801,7 @@ void tftp_start(enum proto_t protocol) tftp_our_port = simple_strtol(ep, NULL, 10); #endif tftp_cur_block = 0; - + tftp_windowsize = 1; /* zero out server ether in case the server ip has changed */ memset(net_server_ethaddr, 0, 6); /* Revert tftp_block_size to dflt */